[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 NTSTATUS
50 USBSTOR_SendCBW(
51 IN PDEVICE_OBJECT DeviceObject,
52 IN UCHAR CommandBlockLength,
53 IN PUCHAR CommandBlock,
54 IN ULONG DataTransferLength,
55 OUT PCBW *OutControl)
56 {
57 PCBW Control;
58 NTSTATUS Status;
59 PURB Urb;
60 PPDO_DEVICE_EXTENSION PDODeviceExtension;
61 PFDO_DEVICE_EXTENSION FDODeviceExtension;
62
63 //
64 // get PDO device extension
65 //
66 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
67
68 //
69 // get FDO device extension
70 //
71 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)PDODeviceExtension->LowerDeviceObject->DeviceExtension;
72
73 //
74 // first allocate CBW
75 //
76 Control = (PCBW)AllocateItem(NonPagedPool, 512);
77 if (!Control)
78 {
79 //
80 // no memory
81 //
82 return STATUS_INSUFFICIENT_RESOURCES;
83 }
84
85 //
86 // first allocate CBW
87 //
88 Status = USBSTOR_BuildCBW(0xDEADDEAD, DataTransferLength, PDODeviceExtension->LUN, CommandBlockLength, CommandBlock, Control);
89 if (!NT_SUCCESS(Status))
90 {
91 //
92 // failed to build CBW
93 //
94 return Status;
95 }
96
97 //
98 // now build the urb
99 //
100 Urb = (PURB)AllocateItem(NonPagedPool, sizeof(URB));
101 if (!Urb)
102 {
103 //
104 // failed to allocate urb
105 //
106 FreeItem(Control);
107 return STATUS_INSUFFICIENT_RESOURCES;
108 }
109
110 //
111 // now initialize the urb
112 //
113 Urb->UrbBulkOrInterruptTransfer.Hdr.Length = sizeof(URB);
114 Urb->UrbBulkOrInterruptTransfer.Hdr.Function = URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER;
115 Urb->UrbBulkOrInterruptTransfer.PipeHandle = FDODeviceExtension->InterfaceInformation->Pipes[FDODeviceExtension->BulkOutPipeIndex].PipeHandle;
116 Urb->UrbBulkOrInterruptTransfer.TransferBuffer = (PVOID)Control;
117 Urb->UrbBulkOrInterruptTransfer.TransferBufferLength = sizeof(CBW);
118 Urb->UrbBulkOrInterruptTransfer.TransferFlags = USBD_TRANSFER_DIRECTION_OUT | USBD_SHORT_TRANSFER_OK;
119
120 //
121 // now send urb
122 //
123 Status = USBSTOR_SyncUrbRequest(FDODeviceExtension->LowerDeviceObject, Urb);
124
125 //
126 // free urb
127 //
128 FreeItem(Urb);
129
130 //
131 // store cbw
132 //
133 *OutControl = Control;
134
135 //
136 // return operation status
137 //
138 return Status;
139 }
140
141 NTSTATUS
142 USBSTOR_SendData(
143 IN PDEVICE_OBJECT DeviceObject,
144 IN ULONG DataTransferLength,
145 IN PVOID DataTransfer)
146 {
147 PMDL TransferBufferMDL;
148 PURB Urb;
149 NTSTATUS Status;
150 PPDO_DEVICE_EXTENSION PDODeviceExtension;
151 PFDO_DEVICE_EXTENSION FDODeviceExtension;
152
153 //
154 // get PDO device extension
155 //
156 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
157
158 //
159 // get FDO device extension
160 //
161 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)PDODeviceExtension->LowerDeviceObject->DeviceExtension;
162
163 //
164 // allocate mdl for buffer, buffer must be allocated from NonPagedPool
165 //
166 TransferBufferMDL = IoAllocateMdl(DataTransfer, DataTransferLength, FALSE, FALSE, NULL);
167 if (!TransferBufferMDL)
168 {
169 //
170 // failed to allocate MDL
171 //
172 return STATUS_INSUFFICIENT_RESOURCES;
173 }
174
175 //
176 // build mdl for nonpaged pool
177 //
178 MmBuildMdlForNonPagedPool(TransferBufferMDL);
179
180 //
181 // now build the urb
182 //
183 Urb = (PURB)AllocateItem(NonPagedPool, sizeof(URB));
184 if (!Urb)
185 {
186 //
187 // failed to allocate urb
188 //
189 IoFreeMdl(TransferBufferMDL);
190 return STATUS_INSUFFICIENT_RESOURCES;
191 }
192
193 //
194 // now initialize the urb
195 //
196 Urb->UrbBulkOrInterruptTransfer.Hdr.Length = sizeof(URB);
197 Urb->UrbBulkOrInterruptTransfer.Hdr.Function = URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER;
198 Urb->UrbBulkOrInterruptTransfer.PipeHandle = FDODeviceExtension->InterfaceInformation->Pipes[FDODeviceExtension->BulkInPipeIndex].PipeHandle;
199 Urb->UrbBulkOrInterruptTransfer.TransferBufferMDL = TransferBufferMDL;
200 Urb->UrbBulkOrInterruptTransfer.TransferBufferLength = DataTransferLength;
201 Urb->UrbBulkOrInterruptTransfer.TransferFlags = USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK;
202
203 //
204 // now send urb
205 //
206 Status = USBSTOR_SyncUrbRequest(FDODeviceExtension->LowerDeviceObject, Urb);
207
208 //
209 // free urb
210 //
211 FreeItem(Urb);
212
213 //
214 // free mdl
215 //
216 IoFreeMdl(TransferBufferMDL);
217
218 //
219 // done
220 //
221 return Status;
222 }
223
224 NTSTATUS
225 USBSTOR_SendCSW(
226 IN PDEVICE_OBJECT DeviceObject,
227 IN PVOID Data,
228 IN ULONG DataLength,
229 OUT PCSW OutCSW)
230 {
231 NTSTATUS Status;
232 PPDO_DEVICE_EXTENSION PDODeviceExtension;
233 PFDO_DEVICE_EXTENSION FDODeviceExtension;
234 PURB Urb;
235
236 //
237 // get PDO device extension
238 //
239 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
240
241 //
242 // get FDO device extension
243 //
244 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)PDODeviceExtension->LowerDeviceObject->DeviceExtension;
245
246 //
247 // now build the urb
248 //
249 Urb = (PURB)AllocateItem(NonPagedPool, sizeof(URB));
250 if (!Urb)
251 {
252 //
253 // failed to allocate urb
254 //
255 return STATUS_INSUFFICIENT_RESOURCES;
256 }
257
258 //
259 // now initialize the urb
260 //
261 Urb->UrbBulkOrInterruptTransfer.Hdr.Length = sizeof(URB);
262 Urb->UrbBulkOrInterruptTransfer.Hdr.Function = URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER;
263 Urb->UrbBulkOrInterruptTransfer.PipeHandle = FDODeviceExtension->InterfaceInformation->Pipes[FDODeviceExtension->BulkInPipeIndex].PipeHandle;
264 Urb->UrbBulkOrInterruptTransfer.TransferBuffer = Data;
265 Urb->UrbBulkOrInterruptTransfer.TransferBufferLength = DataLength;
266 Urb->UrbBulkOrInterruptTransfer.TransferFlags = USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK;
267
268 //
269 // now send urb
270 //
271 Status = USBSTOR_SyncUrbRequest(FDODeviceExtension->LowerDeviceObject, Urb);
272
273 if (NT_SUCCESS(Status))
274 {
275 //
276 // copy csw status
277 //
278 RtlCopyMemory(OutCSW, Data, sizeof(CSW));
279 }
280
281 //
282 // free urb
283 //
284 FreeItem(Urb);
285
286 //
287 // done
288 //
289 return Status;
290 }
291
292 NTSTATUS
293 USBSTOR_SendInquiryCmd(
294 IN PDEVICE_OBJECT DeviceObject)
295 {
296 UFI_INQUIRY_CMD Cmd;
297 CSW CSW;
298 NTSTATUS Status;
299 PUFI_INQUIRY_RESPONSE Response;
300 PPDO_DEVICE_EXTENSION PDODeviceExtension;
301 PCBW OutControl;
302
303 //
304 // get PDO device extension
305 //
306 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
307
308 //
309 // allocate inquiry response
310 //
311 Response = (PUFI_INQUIRY_RESPONSE)AllocateItem(NonPagedPool, sizeof(UFI_INQUIRY_RESPONSE));
312 if (!Response)
313 {
314 //
315 // no memory
316 //
317 return STATUS_INSUFFICIENT_RESOURCES;
318 }
319
320 //
321 // initialize inquiry cmd
322 //
323 RtlZeroMemory(&Cmd, sizeof(UFI_INQUIRY_CMD));
324 Cmd.Code = SCSIOP_INQUIRY;
325 Cmd.LUN = (PDODeviceExtension->LUN & MAX_LUN);
326 Cmd.AllocationLength = sizeof(UFI_INQUIRY_RESPONSE);
327
328 //
329 // now send inquiry cmd
330 //
331 Status = USBSTOR_SendCBW(DeviceObject, UFI_INQUIRY_CMD_LEN, (PUCHAR)&Cmd, sizeof(UFI_INQUIRY_RESPONSE), &OutControl);
332 if (!NT_SUCCESS(Status))
333 {
334 //
335 // failed to send CBW
336 //
337 DPRINT1("USBSTOR_SendInquiryCmd> USBSTOR_SendCBW failed with %x\n", Status);
338 FreeItem(Response);
339 ASSERT(FALSE);
340 return Status;
341 }
342
343 //
344 // now send inquiry response
345 //
346 Status = USBSTOR_SendData(DeviceObject, sizeof(UFI_INQUIRY_RESPONSE), Response);
347 if (!NT_SUCCESS(Status))
348 {
349 //
350 // failed to send CBW
351 //
352 DPRINT1("USBSTOR_SendInquiryCmd> USBSTOR_SendData failed with %x\n", Status);
353 FreeItem(Response);
354 ASSERT(FALSE);
355 return Status;
356 }
357
358 DPRINT1("Response %p\n", Response);
359 DPRINT1("DeviceType %x\n", Response->DeviceType);
360 DPRINT1("RMB %x\n", Response->RMB);
361 DPRINT1("Version %x\n", Response->Version);
362 DPRINT1("Format %x\n", Response->Format);
363 DPRINT1("Length %x\n", Response->Length);
364 DPRINT1("Reserved %x\n", Response->Reserved);
365 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]);
366 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],
367 Response->Product[4], Response->Product[5], Response->Product[6], Response->Product[7],
368 Response->Product[8], Response->Product[9], Response->Product[10], Response->Product[11],
369 Response->Product[12], Response->Product[13], Response->Product[14], Response->Product[15]);
370
371 DPRINT1("Revision %c%c%c%c\n", Response->Revision[0], Response->Revision[1], Response->Revision[2], Response->Revision[3]);
372
373 //
374 // send csw
375 //
376 Status = USBSTOR_SendCSW(DeviceObject, OutControl, 512, &CSW);
377
378 DPRINT1("------------------------\n");
379 DPRINT1("CSW %p\n", &CSW);
380 DPRINT1("Signature %x\n", CSW.Signature);
381 DPRINT1("Tag %x\n", CSW.Tag);
382 DPRINT1("DataResidue %x\n", CSW.DataResidue);
383 DPRINT1("Status %x\n", CSW.Status);
384
385 //
386 // free item
387 //
388 FreeItem(OutControl);
389
390 //
391 // store inquiry data
392 //
393 PDODeviceExtension->InquiryData = (PVOID)Response;
394
395 //
396 // FIXME: handle error
397 //
398 ASSERT(CSW.Status == 0);
399
400
401 //
402 // done
403 //
404 return Status;
405 }
406
407 NTSTATUS
408 USBSTOR_SendCapacityCmd(
409 IN PDEVICE_OBJECT DeviceObject,
410 OUT PREAD_CAPACITY_DATA_EX CapacityDataEx,
411 OUT PREAD_CAPACITY_DATA CapacityData)
412 {
413 UFI_CAPACITY_CMD Cmd;
414 CSW CSW;
415 NTSTATUS Status;
416 PUFI_CAPACITY_RESPONSE Response;
417 PPDO_DEVICE_EXTENSION PDODeviceExtension;
418 PCBW OutControl;
419
420 //
421 // get PDO device extension
422 //
423 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
424
425 //
426 // allocate capacity response
427 //
428 Response = (PUFI_CAPACITY_RESPONSE)AllocateItem(NonPagedPool, sizeof(UFI_CAPACITY_RESPONSE));
429 if (!Response)
430 {
431 //
432 // no memory
433 //
434 return STATUS_INSUFFICIENT_RESOURCES;
435 }
436
437 //
438 // initialize capacity cmd
439 //
440 RtlZeroMemory(&Cmd, sizeof(UFI_INQUIRY_CMD));
441 Cmd.Code = SCSIOP_READ_CAPACITY;
442 Cmd.LUN = (PDODeviceExtension->LUN & MAX_LUN);
443
444 //
445 // now send capacity cmd
446 //
447 Status = USBSTOR_SendCBW(DeviceObject, UFI_CAPACITY_CMD_LEN, (PUCHAR)&Cmd, sizeof(UFI_CAPACITY_RESPONSE), &OutControl);
448 if (!NT_SUCCESS(Status))
449 {
450 //
451 // failed to send CBW
452 //
453 DPRINT1("USBSTOR_SendCapacityCmd> USBSTOR_SendCBW failed with %x\n", Status);
454 FreeItem(Response);
455 ASSERT(FALSE);
456 return Status;
457 }
458
459 //
460 // now send inquiry response
461 //
462 Status = USBSTOR_SendData(DeviceObject, sizeof(UFI_CAPACITY_RESPONSE), Response);
463 if (!NT_SUCCESS(Status))
464 {
465 //
466 // failed to send CBW
467 //
468 DPRINT1("USBSTOR_SendCapacityCmd> USBSTOR_SendData failed with %x\n", Status);
469 FreeItem(Response);
470 ASSERT(FALSE);
471 return Status;
472 }
473
474 DPRINT1("LastLogicalBlockAddress %lu\n", NTOHL(Response->LastLogicalBlockAddress));
475 DPRINT1("BlockLength %lu\n", NTOHL(Response->BlockLength));
476 DPRINT1("Medium Length %lu\n", NTOHL(Response->BlockLength) * NTOHL(Response->LastLogicalBlockAddress));
477
478 //
479 // store response
480 //
481 if (CapacityDataEx)
482 {
483 CapacityDataEx->LogicalBlockAddress.QuadPart = Response->LastLogicalBlockAddress;
484 CapacityDataEx->BytesPerBlock = Response->BlockLength;
485 }
486 else
487 {
488 CapacityData->LogicalBlockAddress = Response->LastLogicalBlockAddress;
489 CapacityData->BytesPerBlock = Response->BlockLength;
490 }
491
492 //
493 // store result in device extension
494 //
495 PDODeviceExtension->LastLogicBlockAddress = NTOHL(Response->LastLogicalBlockAddress);
496 PDODeviceExtension->BlockLength = NTOHL(Response->BlockLength);
497
498 //
499 // send csw
500 //
501 Status = USBSTOR_SendCSW(DeviceObject, OutControl, 512, &CSW);
502
503 DPRINT1("------------------------\n");
504 DPRINT1("CSW %p\n", &CSW);
505 DPRINT1("Signature %x\n", CSW.Signature);
506 DPRINT1("Tag %x\n", CSW.Tag);
507 DPRINT1("DataResidue %x\n", CSW.DataResidue);
508 DPRINT1("Status %x\n", CSW.Status);
509
510 //
511 // FIXME: handle error
512 //
513 ASSERT(CSW.Status == 0);
514
515 //
516 // free item
517 //
518 FreeItem(OutControl);
519
520 //
521 // free response
522 //
523 FreeItem(Response);
524
525 //
526 // done
527 //
528 return Status;
529 }
530
531 NTSTATUS
532 USBSTOR_SendModeSenseCmd(
533 IN PDEVICE_OBJECT DeviceObject,
534 IN OUT PSCSI_REQUEST_BLOCK Request,
535 OUT PULONG TransferBufferLength)
536 {
537 UFI_SENSE_CMD Cmd;
538 CSW CSW;
539 NTSTATUS Status;
540 PVOID Response;
541 PPDO_DEVICE_EXTENSION PDODeviceExtension;
542 PCBW OutControl;
543 PCDB pCDB;
544 PUFI_MODE_PARAMETER_HEADER Header;
545
546 //
547 // get SCSI command data block
548 //
549 pCDB = (PCDB)Request->Cdb;
550
551 //
552 // get PDO device extension
553 //
554 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
555
556 //
557 // allocate sense response from non paged pool
558 //
559 Response = (PUFI_CAPACITY_RESPONSE)AllocateItem(NonPagedPool, Request->DataTransferLength);
560 if (!Response)
561 {
562 //
563 // no memory
564 //
565 return STATUS_INSUFFICIENT_RESOURCES;
566 }
567
568 //
569 // sanity check
570 //
571
572
573 // Supported pages
574 // MODE_PAGE_ERROR_RECOVERY
575 // MODE_PAGE_FLEXIBILE
576 // MODE_PAGE_LUN_MAPPING
577 // MODE_PAGE_FAULT_REPORTING
578 // MODE_SENSE_RETURN_ALL
579
580 //
581 // initialize mode sense cmd
582 //
583 RtlZeroMemory(&Cmd, sizeof(UFI_INQUIRY_CMD));
584 Cmd.Code = SCSIOP_MODE_SENSE;
585 Cmd.LUN = (PDODeviceExtension->LUN & MAX_LUN);
586 Cmd.PageCode = pCDB->MODE_SENSE.PageCode;
587 Cmd.PC = pCDB->MODE_SENSE.Pc;
588 Cmd.AllocationLength = HTONS(pCDB->MODE_SENSE.AllocationLength);
589
590 DPRINT1("PageCode %x\n", pCDB->MODE_SENSE.PageCode);
591 DPRINT1("PC %x\n", pCDB->MODE_SENSE.Pc);
592
593 //
594 // now send mode sense cmd
595 //
596 Status = USBSTOR_SendCBW(DeviceObject, UFI_SENSE_CMD_LEN, (PUCHAR)&Cmd, Request->DataTransferLength, &OutControl);
597 if (!NT_SUCCESS(Status))
598 {
599 //
600 // failed to send CBW
601 //
602 DPRINT1("USBSTOR_SendCapacityCmd> USBSTOR_SendCBW failed with %x\n", Status);
603 FreeItem(Response);
604 ASSERT(FALSE);
605 return Status;
606 }
607
608 //
609 // now send data block response
610 //
611 Status = USBSTOR_SendData(DeviceObject, Request->DataTransferLength, Response);
612 if (!NT_SUCCESS(Status))
613 {
614 //
615 // failed to send CBW
616 //
617 DPRINT1("USBSTOR_SendCapacityCmd> USBSTOR_SendData failed with %x\n", Status);
618 FreeItem(Response);
619 ASSERT(FALSE);
620 return Status;
621 }
622
623 Header = (PUFI_MODE_PARAMETER_HEADER)Response;
624
625 //
626 // TODO: build layout
627 //
628 // first struct is the header
629 // MODE_PARAMETER_HEADER / _MODE_PARAMETER_HEADER10
630 //
631 // followed by
632 // MODE_PARAMETER_BLOCK
633 //
634 //
635 DbgBreakPoint();
636
637 //
638 // send csw
639 //
640 Status = USBSTOR_SendCSW(DeviceObject, OutControl, 512, &CSW);
641
642 DPRINT1("------------------------\n");
643 DPRINT1("CSW %p\n", &CSW);
644 DPRINT1("Signature %x\n", CSW.Signature);
645 DPRINT1("Tag %x\n", CSW.Tag);
646 DPRINT1("DataResidue %x\n", CSW.DataResidue);
647 DPRINT1("Status %x\n", CSW.Status);
648
649 //
650 // FIXME: handle error
651 //
652 ASSERT(CSW.Status == 0);
653 ASSERT(CSW.DataResidue == 0);
654
655 //
656 // calculate transfer length
657 //
658 *TransferBufferLength = Request->DataTransferLength - CSW.DataResidue;
659
660 //
661 // copy buffer
662 //
663 RtlCopyMemory(Request->DataBuffer, Response, *TransferBufferLength);
664
665 //
666 // free item
667 //
668 FreeItem(OutControl);
669
670 //
671 // free response
672 //
673 FreeItem(Response);
674
675 //
676 // done
677 //
678 return Status;
679 }
680
681 NTSTATUS
682 USBSTOR_SendReadCmd(
683 IN PDEVICE_OBJECT DeviceObject,
684 IN OUT PSCSI_REQUEST_BLOCK Request,
685 OUT PULONG TransferBufferLength)
686 {
687 UFI_READ_CMD Cmd;
688 CSW CSW;
689 NTSTATUS Status;
690 PVOID Response;
691 PPDO_DEVICE_EXTENSION PDODeviceExtension;
692 PCBW OutControl;
693 PCDB pCDB;
694 ULONG BlockCount;
695
696 //
697 // get SCSI command data block
698 //
699 pCDB = (PCDB)Request->Cdb;
700
701 //
702 // get PDO device extension
703 //
704 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
705
706 //
707 // allocate read buffer response from non paged pool
708 //
709 Response = (PUFI_CAPACITY_RESPONSE)AllocateItem(NonPagedPool, Request->DataTransferLength);
710 if (!Response)
711 {
712 //
713 // no memory
714 //
715 return STATUS_INSUFFICIENT_RESOURCES;
716 }
717
718 //
719 // FIXME: support more logical blocks
720 //
721 ASSERT(Request->DataTransferLength == PDODeviceExtension->BlockLength);
722
723 //
724 // block count
725 //
726 BlockCount = Request->DataTransferLength / PDODeviceExtension->BlockLength;
727
728 //
729 // initialize read sense cmd
730 //
731 RtlZeroMemory(&Cmd, sizeof(UFI_READ_CMD));
732 Cmd.Code = SCSIOP_READ;
733 Cmd.LUN = (PDODeviceExtension->LUN & MAX_LUN);
734 Cmd.ContiguousLogicBlocks = _byteswap_ushort(BlockCount);
735
736 RtlCopyMemory(&Cmd.LogicalBlockAddress, pCDB->READ12.LogicalBlock, sizeof(UCHAR) * 4);
737
738 DPRINT1("BlockAddress %lu BlockCount %lu BlockLength %lu\n", NTOHL(Cmd.LogicalBlockAddress), BlockCount, PDODeviceExtension->BlockLength);
739
740 //
741 // now send read cmd
742 //
743 Status = USBSTOR_SendCBW(DeviceObject, UFI_READ_CMD_LEN, (PUCHAR)&Cmd, Request->DataTransferLength, &OutControl);
744 if (!NT_SUCCESS(Status))
745 {
746 //
747 // failed to send CBW
748 //
749 DPRINT1("USBSTOR_SendReadCmd> USBSTOR_SendCBW failed with %x\n", Status);
750 FreeItem(Response);
751 ASSERT(FALSE);
752 return Status;
753 }
754
755 //
756 // now read the logical block
757 //
758 Status = USBSTOR_SendData(DeviceObject, Request->DataTransferLength, Response);
759 if (!NT_SUCCESS(Status))
760 {
761 //
762 // failed to read logical block
763 //
764 DPRINT1("USBSTOR_SendReadCmd> USBSTOR_SendData failed with %x\n", Status);
765 FreeItem(Response);
766 ASSERT(FALSE);
767 return Status;
768 }
769
770
771 DbgBreakPoint();
772
773 //
774 // send csw
775 //
776 Status = USBSTOR_SendCSW(DeviceObject, OutControl, 512, &CSW);
777
778 DPRINT1("------------------------\n");
779 DPRINT1("CSW %p\n", &CSW);
780 DPRINT1("Signature %x\n", CSW.Signature);
781 DPRINT1("Tag %x\n", CSW.Tag);
782 DPRINT1("DataResidue %x\n", CSW.DataResidue);
783 DPRINT1("Status %x\n", CSW.Status);
784
785 //
786 // FIXME: handle error
787 //
788 ASSERT(CSW.Status == 0);
789 ASSERT(CSW.DataResidue == 0);
790
791 //
792 // calculate transfer length
793 //
794 *TransferBufferLength = Request->DataTransferLength - CSW.DataResidue;
795
796 //
797 // copy buffer
798 //
799 RtlCopyMemory(Request->DataBuffer, Response, *TransferBufferLength);
800
801 //
802 // free item
803 //
804 FreeItem(OutControl);
805
806 //
807 // free response
808 //
809 FreeItem(Response);
810
811 //
812 // done
813 //
814 return Status;
815 }