[IMM32] Improve ImmGetImeInfoEx (#3833)
[reactos.git] / drivers / storage / class / class2 / class2.c
1 /*
2 * PROJECT: ReactOS Storage Stack
3 * LICENSE: DDK - see license.txt in the root dir
4 * FILE: drivers/storage/class2/class2.c
5 * PURPOSE: SCSI Class driver routines
6 * PROGRAMMERS: Based on a source code sample from Microsoft NT4 DDK
7 */
8
9 #include <ntddk.h>
10 #include <ntdddisk.h>
11 #include <mountdev.h>
12 #include <scsi.h>
13 #include <include/class2.h>
14 #include <stdio.h>
15
16 //#define NDEBUG
17 #include <debug.h>
18
19 #ifdef ALLOC_PRAGMA
20 #pragma alloc_text(PAGE, ScsiClassGetInquiryData)
21 #pragma alloc_text(PAGE, ScsiClassInitialize)
22 #pragma alloc_text(PAGE, ScsiClassGetCapabilities)
23 #pragma alloc_text(PAGE, ScsiClassSendSrbSynchronous)
24 #pragma alloc_text(PAGE, ScsiClassClaimDevice)
25 #pragma alloc_text(PAGE, ScsiClassSendSrbAsynchronous)
26 #endif
27
28
29 #define INQUIRY_DATA_SIZE 2048
30 #define START_UNIT_TIMEOUT 30
31
32 /* Disk layout used by Windows NT4 and earlier versions. */
33 //#define DEFAULT_SECTORS_PER_TRACK 32
34 //#define DEFAULT_TRACKS_PER_CYLINDER 64
35
36 /* Disk layout used by Windows 2000 and later versions. */
37 #define DEFAULT_SECTORS_PER_TRACK 63
38 #define DEFAULT_TRACKS_PER_CYLINDER 255
39
40 NTSTATUS
41 NTAPI
42 ScsiClassCreateClose(
43 IN PDEVICE_OBJECT DeviceObject,
44 IN PIRP Irp
45 );
46
47 NTSTATUS
48 NTAPI
49 ScsiClassReadWrite(
50 IN PDEVICE_OBJECT DeviceObject,
51 IN PIRP Irp
52 );
53
54 NTSTATUS
55 NTAPI
56 ScsiClassDeviceControlDispatch(
57 PDEVICE_OBJECT DeviceObject,
58 PIRP Irp
59 );
60
61 NTSTATUS
62 NTAPI
63 ScsiClassDeviceControl(
64 PDEVICE_OBJECT DeviceObject,
65 PIRP Irp
66 );
67
68 NTSTATUS
69 NTAPI
70 ScsiClassInternalIoControl (
71 IN PDEVICE_OBJECT DeviceObject,
72 IN PIRP Irp
73 );
74
75 NTSTATUS
76 NTAPI
77 ScsiClassShutdownFlush(
78 IN PDEVICE_OBJECT DeviceObject,
79 IN PIRP Irp
80 );
81
82 NTSTATUS
83 NTAPI
84 DriverEntry(
85 IN PDRIVER_OBJECT DriverObject,
86 IN PUNICODE_STRING RegistryPath
87 );
88
89 //
90 // Class internal routines
91 //
92
93
94 VOID
95 NTAPI
96 RetryRequest(
97 PDEVICE_OBJECT DeviceObject,
98 PIRP Irp,
99 PSCSI_REQUEST_BLOCK Srb,
100 BOOLEAN Associated
101 );
102
103 VOID
104 NTAPI
105 StartUnit(
106 IN PDEVICE_OBJECT DeviceObject
107 );
108
109 NTSTATUS
110 NTAPI
111 ClassIoCompletion(
112 IN PDEVICE_OBJECT DeviceObject,
113 IN PIRP Irp,
114 IN PVOID Context
115 );
116
117 NTSTATUS
118 NTAPI
119 ClassCompletionRoutine(IN PDEVICE_OBJECT DeviceObject,
120 IN PIRP Irp,
121 IN PVOID Context);
122
123
124 NTSTATUS
125 NTAPI
126 DriverEntry(
127 IN PDRIVER_OBJECT DriverObject,
128 IN PUNICODE_STRING RegistryPath
129 )
130 {
131 return STATUS_SUCCESS;
132 }
133
134 NTSTATUS
135 NTAPI
136 ScsiClassPlugPlay(
137 IN PDEVICE_OBJECT DeviceObject,
138 IN PIRP Irp)
139 {
140 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
141
142 if (IrpSp->MinorFunction == IRP_MN_START_DEVICE)
143 {
144 Irp->IoStatus.Status = STATUS_SUCCESS;
145 IoCompleteRequest(Irp, IO_NO_INCREMENT);
146 return STATUS_SUCCESS;
147 }
148 else
149 {
150 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
151 IoCompleteRequest(Irp, IO_NO_INCREMENT);
152 return STATUS_NOT_SUPPORTED;
153 }
154 }
155
156
157
158 ULONG
159 NTAPI
160 ScsiClassInitialize(
161 IN PVOID Argument1,
162 IN PVOID Argument2,
163 IN PCLASS_INIT_DATA InitializationData
164 )
165
166 /*++
167
168 Routine Description:
169
170 This routine is called by a class driver during its
171 DriverEntry routine to initialize the driver.
172
173 Arguments:
174
175 Argument1 - Driver Object.
176 Argument2 - Registry Path.
177 InitializationData - Device-specific driver's initialization data.
178
179 Return Value:
180
181 A valid return code for a DriverEntry routine.
182
183 --*/
184
185 {
186
187
188 PDRIVER_OBJECT DriverObject = Argument1;
189 ULONG portNumber = 0;
190 PDEVICE_OBJECT portDeviceObject;
191 NTSTATUS status;
192 STRING deviceNameString;
193 UNICODE_STRING unicodeDeviceName;
194 PFILE_OBJECT fileObject;
195 CCHAR deviceNameBuffer[256];
196 BOOLEAN deviceFound = FALSE;
197
198 DebugPrint((3,"\n\nSCSI Class Driver\n"));
199
200 //
201 // Validate the length of this structure. This is effectively a
202 // version check.
203 //
204
205 if (InitializationData->InitializationDataSize > sizeof(CLASS_INIT_DATA)) {
206
207 DebugPrint((0,"ScsiClassInitialize: Class driver wrong version\n"));
208 return (ULONG) STATUS_REVISION_MISMATCH;
209 }
210
211 //
212 // Check that each required entry is not NULL. Note that Shutdown, Flush and Error
213 // are not required entry points.
214 //
215
216 if ((!InitializationData->ClassFindDevices) ||
217 (!InitializationData->ClassDeviceControl) ||
218 (!((InitializationData->ClassReadWriteVerification) ||
219 (InitializationData->ClassStartIo)))) {
220
221 DebugPrint((0,
222 "ScsiClassInitialize: Class device-specific driver missing required entry\n"));
223
224 return (ULONG) STATUS_REVISION_MISMATCH;
225 }
226
227 //
228 // Update driver object with entry points.
229 //
230
231 DriverObject->MajorFunction[IRP_MJ_CREATE] = ScsiClassCreateClose;
232 DriverObject->MajorFunction[IRP_MJ_CLOSE] = ScsiClassCreateClose;
233 DriverObject->MajorFunction[IRP_MJ_READ] = ScsiClassReadWrite;
234 DriverObject->MajorFunction[IRP_MJ_WRITE] = ScsiClassReadWrite;
235 DriverObject->MajorFunction[IRP_MJ_PNP] = ScsiClassPlugPlay;
236 DriverObject->MajorFunction[IRP_MJ_SCSI] = ScsiClassInternalIoControl;
237 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ScsiClassDeviceControlDispatch;
238 DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = ScsiClassShutdownFlush;
239 DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = ScsiClassShutdownFlush;
240
241 if (InitializationData->ClassStartIo) {
242 DriverObject->DriverStartIo = InitializationData->ClassStartIo;
243 }
244
245 //
246 // Open port driver controller device objects by name.
247 //
248
249 do {
250
251 sprintf(deviceNameBuffer, "\\Device\\ScsiPort%lu", portNumber);
252
253 DebugPrint((2, "ScsiClassInitialize: Open Port %s\n", deviceNameBuffer));
254
255 RtlInitString(&deviceNameString, deviceNameBuffer);
256
257 status = RtlAnsiStringToUnicodeString(&unicodeDeviceName,
258 &deviceNameString,
259 TRUE);
260
261 if (!NT_SUCCESS(status)){
262 break;
263 }
264
265 status = IoGetDeviceObjectPointer(&unicodeDeviceName,
266 FILE_READ_ATTRIBUTES,
267 &fileObject,
268 &portDeviceObject);
269
270 if (NT_SUCCESS(status)) {
271
272 //
273 // Call the device-specific driver's FindDevice routine.
274 //
275
276 if (InitializationData->ClassFindDevices(DriverObject, Argument2, InitializationData,
277 portDeviceObject, portNumber)) {
278
279 deviceFound = TRUE;
280 }
281 }
282
283 //
284 // Check next SCSI adapter.
285 //
286
287 portNumber++;
288
289 } while(NT_SUCCESS(status));
290
291 return deviceFound ? STATUS_SUCCESS : STATUS_NO_SUCH_DEVICE;
292 }
293
294
295 NTSTATUS
296 NTAPI
297 ScsiClassCreateClose(
298 IN PDEVICE_OBJECT DeviceObject,
299 IN PIRP Irp
300 )
301
302 /*++
303
304 Routine Description:
305
306 SCSI class driver create and close routine. This is called by the I/O system
307 when the device is opened or closed.
308
309 Arguments:
310
311 DriverObject - Pointer to driver object created by system.
312
313 Irp - IRP involved.
314
315 Return Value:
316
317 Device-specific drivers return value or STATUS_SUCCESS.
318
319 --*/
320
321 {
322 PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
323
324 ASSERT(*(PULONG)deviceExtension != '2slc');
325
326 //
327 // Invoke the device-specific routine, if one exists. Otherwise complete
328 // with SUCCESS
329 //
330
331 if (deviceExtension->ClassCreateClose) {
332
333 return deviceExtension->ClassCreateClose(DeviceObject, Irp);
334
335 } else {
336 Irp->IoStatus.Status = STATUS_SUCCESS;
337
338 IoCompleteRequest(Irp, IO_NO_INCREMENT);
339 return(STATUS_SUCCESS);
340 }
341 }
342
343
344
345 NTSTATUS
346 NTAPI
347 ScsiClassReadWrite(
348 IN PDEVICE_OBJECT DeviceObject,
349 IN PIRP Irp
350 )
351
352 /*++
353
354 Routine Description:
355
356 This is the system entry point for read and write requests. The device-specific handler is invoked
357 to perform any validation necessary. The number of bytes in the request are
358 checked against the maximum byte counts that the adapter supports and requests are broken up into
359 smaller sizes if necessary.
360
361 Arguments:
362
363 DeviceObject
364 Irp - IO request
365
366 Return Value:
367
368 NT Status
369
370 --*/
371
372 {
373 PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
374 PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
375 ULONG transferPages;
376 ULONG transferByteCount = currentIrpStack->Parameters.Read.Length;
377 ULONG maximumTransferLength = deviceExtension->PortCapabilities->MaximumTransferLength;
378 NTSTATUS status;
379
380 ASSERT(*(PULONG)deviceExtension != '2slc');
381
382 if (DeviceObject->Flags & DO_VERIFY_VOLUME &&
383 !(currentIrpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME)) {
384
385 //
386 // if DO_VERIFY_VOLUME bit is set
387 // in device object flags, fail request.
388 //
389
390 IoSetHardErrorOrVerifyDevice(Irp, DeviceObject);
391
392 Irp->IoStatus.Status = STATUS_VERIFY_REQUIRED;
393 Irp->IoStatus.Information = 0;
394
395 IoCompleteRequest(Irp, 0);
396 return STATUS_VERIFY_REQUIRED;
397 }
398
399 //
400 // Invoke the device specific routine to do whatever it needs to verify
401 // this request.
402 //
403
404 ASSERT(deviceExtension->ClassReadWriteVerification);
405
406 status = deviceExtension->ClassReadWriteVerification(DeviceObject,Irp);
407
408 if (!NT_SUCCESS(status)) {
409
410 //
411 // It is up to the device specific driver to set the Irp status.
412 //
413
414 IoCompleteRequest (Irp, IO_NO_INCREMENT);
415 return status;
416 } else if (status == STATUS_PENDING) {
417
418 IoMarkIrpPending(Irp);
419 return STATUS_PENDING;
420 }
421
422 //
423 // Check for a zero length IO, as several macros will turn this into
424 // seemingly a 0xffffffff length request.
425 //
426
427 if (transferByteCount == 0) {
428 Irp->IoStatus.Status = STATUS_SUCCESS;
429 Irp->IoStatus.Information = 0;
430 IoCompleteRequest(Irp, IO_NO_INCREMENT);
431 return STATUS_SUCCESS;
432
433 }
434
435 if (deviceExtension->ClassStartIo) {
436
437 IoMarkIrpPending(Irp);
438
439 IoStartPacket(DeviceObject,
440 Irp,
441 NULL,
442 NULL);
443
444 return STATUS_PENDING;
445 }
446
447 //
448 // Mark IRP with status pending.
449 //
450
451 IoMarkIrpPending(Irp);
452
453 //
454 // Add partition byte offset to make starting byte relative to
455 // beginning of disk. In addition, add in skew for DM Driver, if any.
456 //
457
458 currentIrpStack->Parameters.Read.ByteOffset.QuadPart += (deviceExtension->StartingOffset.QuadPart +
459 deviceExtension->DMByteSkew);
460
461 //
462 // Calculate number of pages in this transfer.
463 //
464
465 transferPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(Irp->MdlAddress),
466 currentIrpStack->Parameters.Read.Length);
467
468 //
469 // Check if request length is greater than the maximum number of
470 // bytes that the hardware can transfer.
471 //
472
473 if (currentIrpStack->Parameters.Read.Length > maximumTransferLength ||
474 transferPages > deviceExtension->PortCapabilities->MaximumPhysicalPages) {
475
476 DebugPrint((2,"ScsiClassReadWrite: Request greater than maximum\n"));
477 DebugPrint((2,"ScsiClassReadWrite: Maximum is %lx\n",
478 maximumTransferLength));
479 DebugPrint((2,"ScsiClassReadWrite: Byte count is %lx\n",
480 currentIrpStack->Parameters.Read.Length));
481
482 transferPages =
483 deviceExtension->PortCapabilities->MaximumPhysicalPages - 1;
484
485 if (maximumTransferLength > transferPages << PAGE_SHIFT ) {
486 maximumTransferLength = transferPages << PAGE_SHIFT;
487 }
488
489 //
490 // Check that maximum transfer size is not zero.
491 //
492
493 if (maximumTransferLength == 0) {
494 maximumTransferLength = PAGE_SIZE;
495 }
496
497 //
498 // Mark IRP with status pending.
499 //
500
501 IoMarkIrpPending(Irp);
502
503 //
504 // Request greater than port driver maximum.
505 // Break up into smaller routines.
506 //
507
508 ScsiClassSplitRequest(DeviceObject, Irp, maximumTransferLength);
509
510
511 return STATUS_PENDING;
512 }
513
514 //
515 // Build SRB and CDB for this IRP.
516 //
517
518 ScsiClassBuildRequest(DeviceObject, Irp);
519
520 //
521 // Return the results of the call to the port driver.
522 //
523
524 return IoCallDriver(deviceExtension->PortDeviceObject, Irp);
525
526 } // end ScsiClassReadWrite()
527
528
529 NTSTATUS
530 NTAPI
531 ScsiClassGetCapabilities(
532 IN PDEVICE_OBJECT PortDeviceObject,
533 OUT PIO_SCSI_CAPABILITIES *PortCapabilities
534 )
535
536 /*++
537
538 Routine Description:
539
540 This routine builds and sends a request to the port driver to
541 get a pointer to a structure that describes the adapter's
542 capabilities/limitations. This routine is synchronous.
543
544 Arguments:
545
546 PortDeviceObject - Port driver device object representing the HBA.
547
548 PortCapabilities - Location to store pointer to capabilities structure.
549
550 Return Value:
551
552 Nt status indicating the results of the operation.
553
554 Notes:
555
556 This routine should only be called at initialization time.
557
558 --*/
559
560 {
561 PIRP irp;
562 IO_STATUS_BLOCK ioStatus;
563 KEVENT event;
564 NTSTATUS status;
565
566 PAGED_CODE();
567
568 //
569 // Create notification event object to be used to signal the
570 // request completion.
571 //
572
573 KeInitializeEvent(&event, NotificationEvent, FALSE);
574
575 //
576 // Build the synchronous request to be sent to the port driver
577 // to perform the request.
578 //
579
580 irp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_GET_CAPABILITIES,
581 PortDeviceObject,
582 NULL,
583 0,
584 PortCapabilities,
585 sizeof(PVOID),
586 FALSE,
587 &event,
588 &ioStatus);
589
590 if (irp == NULL) {
591 return STATUS_INSUFFICIENT_RESOURCES;
592 }
593
594 //
595 // Pass request to port driver and wait for request to complete.
596 //
597
598 status = IoCallDriver(PortDeviceObject, irp);
599
600 if (status == STATUS_PENDING) {
601 KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, NULL);
602 return(ioStatus.Status);
603 }
604
605 return status;
606
607 } // end ScsiClassGetCapabilities()
608
609
610 NTSTATUS
611 NTAPI
612 ScsiClassGetInquiryData(
613 IN PDEVICE_OBJECT PortDeviceObject,
614 OUT PSCSI_ADAPTER_BUS_INFO *ConfigInfo
615 )
616
617 /*++
618
619 Routine Description:
620
621 This routine sends a request to a port driver to return
622 configuration information. Space for the information is
623 allocated by this routine. The caller is responsible for
624 freeing the configuration information. This routine is
625 synchronous.
626
627 Arguments:
628
629 PortDeviceObject - Port driver device object representing the HBA.
630
631 ConfigInfo - Returns a pointer to the configuration information.
632
633 Return Value:
634
635 Nt status indicating the results of the operation.
636
637 Notes:
638
639 This routine should be called only at initialization time.
640
641 --*/
642
643 {
644 PIRP irp;
645 IO_STATUS_BLOCK ioStatus;
646 KEVENT event;
647 NTSTATUS status;
648 PSCSI_ADAPTER_BUS_INFO buffer;
649
650 PAGED_CODE();
651
652 buffer = ExAllocatePool(PagedPool, INQUIRY_DATA_SIZE);
653 *ConfigInfo = buffer;
654
655 if (buffer == NULL) {
656 return(STATUS_INSUFFICIENT_RESOURCES);
657 }
658
659 //
660 // Create notification event object to be used to signal the inquiry
661 // request completion.
662 //
663
664 KeInitializeEvent(&event, NotificationEvent, FALSE);
665
666 //
667 // Build the synchronous request to be sent to the port driver
668 // to perform the inquiries.
669 //
670
671 irp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_GET_INQUIRY_DATA,
672 PortDeviceObject,
673 NULL,
674 0,
675 buffer,
676 INQUIRY_DATA_SIZE,
677 FALSE,
678 &event,
679 &ioStatus);
680
681 if (irp == NULL) {
682 return(STATUS_INSUFFICIENT_RESOURCES);
683 }
684
685 //
686 // Pass request to port driver and wait for request to complete.
687 //
688
689 status = IoCallDriver(PortDeviceObject, irp);
690
691 if (status == STATUS_PENDING) {
692 KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, NULL);
693 status = ioStatus.Status;
694 }
695
696 if (!NT_SUCCESS(status)) {
697
698 //
699 // Free the buffer on an error.
700 //
701
702 ExFreePool(buffer);
703 *ConfigInfo = NULL;
704
705 }
706
707 return status;
708
709 } // end ScsiClassGetInquiryData()
710
711
712 NTSTATUS
713 NTAPI
714 ScsiClassReadDriveCapacity(
715 IN PDEVICE_OBJECT DeviceObject
716 )
717
718 /*++
719
720 Routine Description:
721
722 This routine sends a READ CAPACITY to the requested device, updates
723 the geometry information in the device object and returns
724 when it is complete. This routine is synchronous.
725
726 Arguments:
727
728 DeviceObject - Supplies a pointer to the device object that represents
729 the device whose capacity is to be read.
730
731 Return Value:
732
733 Status is returned.
734
735 --*/
736 {
737 PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
738 ULONG retries = 1;
739 ULONG lastSector;
740 PCDB cdb;
741 PREAD_CAPACITY_DATA readCapacityBuffer;
742 SCSI_REQUEST_BLOCK srb;
743 NTSTATUS status;
744
745 ASSERT(*(PULONG)deviceExtension != '2slc');
746
747 //
748 // Allocate read capacity buffer from nonpaged pool.
749 //
750
751 readCapacityBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
752 sizeof(READ_CAPACITY_DATA));
753
754 if (!readCapacityBuffer) {
755 return(STATUS_INSUFFICIENT_RESOURCES);
756 }
757
758 RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK));
759
760 //
761 // Build the read capacity CDB.
762 //
763
764 srb.CdbLength = 10;
765 cdb = (PCDB)srb.Cdb;
766
767 //
768 // Set timeout value from device extension.
769 //
770
771 srb.TimeOutValue = deviceExtension->TimeOutValue;
772
773 cdb->CDB10.OperationCode = SCSIOP_READ_CAPACITY;
774
775 Retry:
776
777 status = ScsiClassSendSrbSynchronous(DeviceObject,
778 &srb,
779 readCapacityBuffer,
780 sizeof(READ_CAPACITY_DATA),
781 FALSE);
782
783 if (NT_SUCCESS(status)) {
784
785 //
786 // Copy sector size from read capacity buffer to device extension
787 // in reverse byte order.
788 //
789
790 ((PFOUR_BYTE)&deviceExtension->DiskGeometry->Geometry.BytesPerSector)->Byte0 =
791 ((PFOUR_BYTE)&readCapacityBuffer->BytesPerBlock)->Byte3;
792
793 ((PFOUR_BYTE)&deviceExtension->DiskGeometry->Geometry.BytesPerSector)->Byte1 =
794 ((PFOUR_BYTE)&readCapacityBuffer->BytesPerBlock)->Byte2;
795
796 ((PFOUR_BYTE)&deviceExtension->DiskGeometry->Geometry.BytesPerSector)->Byte2 =
797 ((PFOUR_BYTE)&readCapacityBuffer->BytesPerBlock)->Byte1;
798
799 ((PFOUR_BYTE)&deviceExtension->DiskGeometry->Geometry.BytesPerSector)->Byte3 =
800 ((PFOUR_BYTE)&readCapacityBuffer->BytesPerBlock)->Byte0;
801
802 //
803 // Copy last sector in reverse byte order.
804 //
805
806 ((PFOUR_BYTE)&lastSector)->Byte0 =
807 ((PFOUR_BYTE)&readCapacityBuffer->LogicalBlockAddress)->Byte3;
808
809 ((PFOUR_BYTE)&lastSector)->Byte1 =
810 ((PFOUR_BYTE)&readCapacityBuffer->LogicalBlockAddress)->Byte2;
811
812 ((PFOUR_BYTE)&lastSector)->Byte2 =
813 ((PFOUR_BYTE)&readCapacityBuffer->LogicalBlockAddress)->Byte1;
814
815 ((PFOUR_BYTE)&lastSector)->Byte3 =
816 ((PFOUR_BYTE)&readCapacityBuffer->LogicalBlockAddress)->Byte0;
817
818 //
819 // Calculate sector to byte shift.
820 //
821
822 WHICH_BIT(deviceExtension->DiskGeometry->Geometry.BytesPerSector, deviceExtension->SectorShift);
823
824 DebugPrint((2,"SCSI ScsiClassReadDriveCapacity: Sector size is %d\n",
825 deviceExtension->DiskGeometry->Geometry.BytesPerSector));
826
827 DebugPrint((2,"SCSI ScsiClassReadDriveCapacity: Number of Sectors is %d\n",
828 lastSector + 1));
829
830 //
831 // Calculate number of cylinders.
832 //
833
834 deviceExtension->DiskGeometry->Geometry.Cylinders.QuadPart = (LONGLONG)((lastSector + 1)/(DEFAULT_SECTORS_PER_TRACK * DEFAULT_TRACKS_PER_CYLINDER));
835
836 //
837 // Calculate media capacity in bytes.
838 //
839
840 deviceExtension->PartitionLength.QuadPart = (LONGLONG)(lastSector + 1);
841 deviceExtension->PartitionLength.QuadPart =
842 (deviceExtension->PartitionLength.QuadPart << deviceExtension->SectorShift);
843 deviceExtension->DiskGeometry->DiskSize.QuadPart = deviceExtension->PartitionLength.QuadPart;
844
845 if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) {
846
847 //
848 // This device supports removable media.
849 //
850
851 deviceExtension->DiskGeometry->Geometry.MediaType = RemovableMedia;
852
853 } else {
854
855 //
856 // Assume media type is fixed disk.
857 //
858
859 deviceExtension->DiskGeometry->Geometry.MediaType = FixedMedia;
860 }
861
862 //
863 // Assume sectors per track are DEFAULT_SECTORS_PER_TRACK;
864 //
865
866 deviceExtension->DiskGeometry->Geometry.SectorsPerTrack = DEFAULT_SECTORS_PER_TRACK;
867
868 //
869 // Assume tracks per cylinder (number of heads) is DEFAULT_TRACKS_PER_CYLINDER.
870 //
871
872 deviceExtension->DiskGeometry->Geometry.TracksPerCylinder = DEFAULT_TRACKS_PER_CYLINDER;
873 }
874
875 if (status == STATUS_VERIFY_REQUIRED) {
876
877 //
878 // Routine ScsiClassSendSrbSynchronous does not retry
879 // requests returned with this status.
880 // Read Capacities should be retried
881 // anyway.
882 //
883
884 if (retries--) {
885
886 //
887 // Retry request.
888 //
889
890 goto Retry;
891 }
892 }
893
894 if (!NT_SUCCESS(status)) {
895
896 //
897 // If the read capacity fails, set the geometry to reasonable parameter
898 // so things don't fail at unexpected places. Zero the geometry
899 // except for the bytes per sector and sector shift.
900 //
901
902 RtlZeroMemory(deviceExtension->DiskGeometry, sizeof(DISK_GEOMETRY_EX));
903 deviceExtension->DiskGeometry->Geometry.BytesPerSector = 512;
904 deviceExtension->SectorShift = 9;
905 deviceExtension->PartitionLength.QuadPart = (LONGLONG) 0;
906 deviceExtension->DiskGeometry->DiskSize.QuadPart = (LONGLONG) 0;
907
908 if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) {
909
910 //
911 // This device supports removable media.
912 //
913
914 deviceExtension->DiskGeometry->Geometry.MediaType = RemovableMedia;
915
916 } else {
917
918 //
919 // Assume media type is fixed disk.
920 //
921
922 deviceExtension->DiskGeometry->Geometry.MediaType = FixedMedia;
923 }
924 }
925
926 //
927 // Deallocate read capacity buffer.
928 //
929
930 ExFreePool(readCapacityBuffer);
931
932 return status;
933
934 } // end ScsiClassReadDriveCapacity()
935
936
937 VOID
938 NTAPI
939 ScsiClassReleaseQueue(
940 IN PDEVICE_OBJECT DeviceObject
941 )
942
943 /*++
944
945 Routine Description:
946
947 This routine issues an internal device control command
948 to the port driver to release a frozen queue. The call
949 is issued asynchronously as ScsiClassReleaseQueue will be invoked
950 from the IO completion DPC (and will have no context to
951 wait for a synchronous call to complete).
952
953 Arguments:
954
955 DeviceObject - The device object for the logical unit with
956 the frozen queue.
957
958 Return Value:
959
960 None.
961
962 --*/
963 {
964 PIO_STACK_LOCATION irpStack;
965 PIRP irp;
966 PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
967 PCOMPLETION_CONTEXT context;
968 PSCSI_REQUEST_BLOCK srb;
969 KIRQL currentIrql;
970
971 ASSERT(*(PULONG)deviceExtension != '2slc');
972
973 //
974 // Allocate context from nonpaged pool.
975 //
976
977 context = ExAllocatePool(NonPagedPoolMustSucceed,
978 sizeof(COMPLETION_CONTEXT));
979
980 //
981 // Save the device object in the context for use by the completion
982 // routine.
983 //
984
985 context->DeviceObject = DeviceObject;
986 srb = &context->Srb;
987
988 //
989 // Zero out srb.
990 //
991
992 RtlZeroMemory(srb, SCSI_REQUEST_BLOCK_SIZE);
993
994 //
995 // Write length to SRB.
996 //
997
998 srb->Length = SCSI_REQUEST_BLOCK_SIZE;
999
1000 //
1001 // Set up SCSI bus address.
1002 //
1003
1004 srb->PathId = deviceExtension->PathId;
1005 srb->TargetId = deviceExtension->TargetId;
1006 srb->Lun = deviceExtension->Lun;
1007
1008 //
1009 // If this device is removable then flush the queue. This will also
1010 // release it.
1011 //
1012
1013 if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) {
1014
1015 srb->Function = SRB_FUNCTION_FLUSH_QUEUE;
1016
1017 } else {
1018
1019 srb->Function = SRB_FUNCTION_RELEASE_QUEUE;
1020
1021 }
1022
1023 //
1024 // Build the asynchronous request to be sent to the port driver.
1025 //
1026
1027 irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
1028
1029 if(irp == NULL) {
1030
1031 //
1032 // We have no better way of dealing with this at the moment
1033 //
1034
1035 KeBugCheck((ULONG)0x0000002DL);
1036
1037 }
1038
1039 IoSetCompletionRoutine(irp,
1040 (PIO_COMPLETION_ROUTINE)ScsiClassAsynchronousCompletion,
1041 context,
1042 TRUE,
1043 TRUE,
1044 TRUE);
1045
1046 irpStack = IoGetNextIrpStackLocation(irp);
1047
1048 irpStack->MajorFunction = IRP_MJ_SCSI;
1049
1050 srb->OriginalRequest = irp;
1051
1052 //
1053 // Store the SRB address in next stack for port driver.
1054 //
1055
1056 irpStack->Parameters.Scsi.Srb = srb;
1057
1058 //
1059 // Since this routine can cause outstanding requests to be completed, and
1060 // calling a completion routine at < DISPATCH_LEVEL is dangerous (if they
1061 // call IoStartNextPacket we will bugcheck) raise up to dispatch level before
1062 // issuing the request
1063 //
1064
1065 currentIrql = KeGetCurrentIrql();
1066
1067 if(currentIrql < DISPATCH_LEVEL) {
1068 KeRaiseIrql(DISPATCH_LEVEL, &currentIrql);
1069 IoCallDriver(deviceExtension->PortDeviceObject, irp);
1070 KeLowerIrql(currentIrql);
1071 } else {
1072 IoCallDriver(deviceExtension->PortDeviceObject, irp);
1073 }
1074
1075 return;
1076
1077 } // end ScsiClassReleaseQueue()
1078
1079
1080 VOID
1081 NTAPI
1082 StartUnit(
1083 IN PDEVICE_OBJECT DeviceObject
1084 )
1085
1086 /*++
1087
1088 Routine Description:
1089
1090 Send command to SCSI unit to start or power up.
1091 Because this command is issued asynchronously, that is, without
1092 waiting on it to complete, the IMMEDIATE flag is not set. This
1093 means that the CDB will not return until the drive has powered up.
1094 This should keep subsequent requests from being submitted to the
1095 device before it has completely spun up.
1096 This routine is called from the InterpretSense routine, when a
1097 request sense returns data indicating that a drive must be
1098 powered up.
1099
1100 Arguments:
1101
1102 DeviceObject - The device object for the logical unit with
1103 the frozen queue.
1104
1105 Return Value:
1106
1107 None.
1108
1109 --*/
1110 {
1111 PIO_STACK_LOCATION irpStack;
1112 PIRP irp;
1113 PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
1114 PSCSI_REQUEST_BLOCK srb;
1115 PCOMPLETION_CONTEXT context;
1116 PCDB cdb;
1117
1118 ASSERT(*(PULONG)deviceExtension != '2slc');
1119
1120 //
1121 // Allocate Srb from nonpaged pool.
1122 //
1123
1124 context = ExAllocatePool(NonPagedPoolMustSucceed,
1125 sizeof(COMPLETION_CONTEXT));
1126
1127 //
1128 // Save the device object in the context for use by the completion
1129 // routine.
1130 //
1131
1132 context->DeviceObject = DeviceObject;
1133 srb = &context->Srb;
1134
1135 //
1136 // Zero out srb.
1137 //
1138
1139 RtlZeroMemory(srb, SCSI_REQUEST_BLOCK_SIZE);
1140
1141 //
1142 // Write length to SRB.
1143 //
1144
1145 srb->Length = SCSI_REQUEST_BLOCK_SIZE;
1146
1147 //
1148 // Set up SCSI bus address.
1149 //
1150
1151 srb->PathId = deviceExtension->PathId;
1152 srb->TargetId = deviceExtension->TargetId;
1153 srb->Lun = deviceExtension->Lun;
1154
1155 srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
1156
1157 //
1158 // Set timeout value large enough for drive to spin up.
1159 //
1160
1161 srb->TimeOutValue = START_UNIT_TIMEOUT;
1162
1163 //
1164 // Set the transfer length.
1165 //
1166
1167 srb->SrbFlags = SRB_FLAGS_NO_DATA_TRANSFER | SRB_FLAGS_DISABLE_AUTOSENSE | SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
1168
1169 //
1170 // Build the start unit CDB.
1171 //
1172
1173 srb->CdbLength = 6;
1174 cdb = (PCDB)srb->Cdb;
1175
1176 cdb->START_STOP.OperationCode = SCSIOP_START_STOP_UNIT;
1177 cdb->START_STOP.Start = 1;
1178 cdb->START_STOP.LogicalUnitNumber = srb->Lun;
1179
1180 //
1181 // Build the asynchronous request to be sent to the port driver.
1182 // Since this routine is called from a DPC the IRP should always be
1183 // available.
1184 //
1185
1186 irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
1187 IoSetCompletionRoutine(irp,
1188 (PIO_COMPLETION_ROUTINE)ScsiClassAsynchronousCompletion,
1189 context,
1190 TRUE,
1191 TRUE,
1192 TRUE);
1193
1194 irpStack = IoGetNextIrpStackLocation(irp);
1195 irpStack->MajorFunction = IRP_MJ_SCSI;
1196 srb->OriginalRequest = irp;
1197
1198 //
1199 // Store the SRB address in next stack for port driver.
1200 //
1201
1202 irpStack->Parameters.Scsi.Srb = srb;
1203
1204 //
1205 // Call the port driver with the IRP.
1206 //
1207
1208 IoCallDriver(deviceExtension->PortDeviceObject, irp);
1209
1210 return;
1211
1212 } // end StartUnit()
1213
1214
1215 NTSTATUS
1216 NTAPI
1217 ScsiClassAsynchronousCompletion(
1218 PDEVICE_OBJECT DeviceObject,
1219 PIRP Irp,
1220 PVOID Context
1221 )
1222 /*++
1223
1224 Routine Description:
1225
1226 This routine is called when an asynchronous I/O request
1227 which was issued by the class driver completes. Examples of such requests
1228 are release queue or START UNIT. This routine releases the queue if
1229 necessary. It then frees the context and the IRP.
1230
1231 Arguments:
1232
1233 DeviceObject - The device object for the logical unit; however since this
1234 is the top stack location the value is NULL.
1235
1236 Irp - Supplies a pointer to the Irp to be processed.
1237
1238 Context - Supplies the context to be used to process this request.
1239
1240 Return Value:
1241
1242 None.
1243
1244 --*/
1245
1246 {
1247 PCOMPLETION_CONTEXT context = Context;
1248 PSCSI_REQUEST_BLOCK srb;
1249
1250 srb = &context->Srb;
1251
1252 //
1253 // If this is an execute srb, then check the return status and make sure.
1254 // the queue is not frozen.
1255 //
1256
1257 if (srb->Function == SRB_FUNCTION_EXECUTE_SCSI) {
1258
1259 //
1260 // Check for a frozen queue.
1261 //
1262
1263 if (srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) {
1264
1265 //
1266 // Unfreeze the queue getting the device object from the context.
1267 //
1268
1269 ScsiClassReleaseQueue(context->DeviceObject);
1270 }
1271 }
1272
1273 //
1274 // Free the context and the Irp.
1275 //
1276
1277 if (Irp->MdlAddress != NULL) {
1278 MmUnlockPages(Irp->MdlAddress);
1279 IoFreeMdl(Irp->MdlAddress);
1280
1281 Irp->MdlAddress = NULL;
1282 }
1283
1284 ExFreePool(context);
1285 IoFreeIrp(Irp);
1286
1287 //
1288 // Indicate the I/O system should stop processing the Irp completion.
1289 //
1290
1291 return STATUS_MORE_PROCESSING_REQUIRED;
1292
1293 } // ScsiClassAsynchronousCompletion()
1294
1295
1296 VOID
1297 NTAPI
1298 ScsiClassSplitRequest(
1299 IN PDEVICE_OBJECT DeviceObject,
1300 IN PIRP Irp,
1301 IN ULONG MaximumBytes
1302 )
1303
1304 /*++
1305
1306 Routine Description:
1307
1308 Break request into smaller requests. Each new request will be the
1309 maximum transfer size that the port driver can handle or if it
1310 is the final request, it may be the residual size.
1311
1312 The number of IRPs required to process this request is written in the
1313 current stack of the original IRP. Then as each new IRP completes
1314 the count in the original IRP is decremented. When the count goes to
1315 zero, the original IRP is completed.
1316
1317 Arguments:
1318
1319 DeviceObject - Pointer to the class device object to be addressed.
1320
1321 Irp - Pointer to Irp the original request.
1322
1323 Return Value:
1324
1325 None.
1326
1327 --*/
1328
1329 {
1330 PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
1331 PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
1332 PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp);
1333 ULONG transferByteCount = currentIrpStack->Parameters.Read.Length;
1334 LARGE_INTEGER startingOffset = currentIrpStack->Parameters.Read.ByteOffset;
1335 PVOID dataBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress);
1336 ULONG dataLength = MaximumBytes;
1337 ULONG irpCount = (transferByteCount + MaximumBytes - 1) / MaximumBytes;
1338 ULONG i;
1339 PSCSI_REQUEST_BLOCK srb;
1340
1341 DebugPrint((2, "ScsiClassSplitRequest: Requires %d IRPs\n", irpCount));
1342 DebugPrint((2, "ScsiClassSplitRequest: Original IRP %lx\n", Irp));
1343
1344 ASSERT(*(PULONG)deviceExtension != '2slc');
1345
1346 //
1347 // If all partial transfers complete successfully then the status and
1348 // bytes transferred are already set up. Failing a partial-transfer IRP
1349 // will set status to error and bytes transferred to 0 during
1350 // IoCompletion. Setting bytes transferred to 0 if an IRP fails allows
1351 // asynchronous partial transfers. This is an optimization for the
1352 // successful case.
1353 //
1354
1355 Irp->IoStatus.Status = STATUS_SUCCESS;
1356 Irp->IoStatus.Information = transferByteCount;
1357
1358 //
1359 // Save number of IRPs to complete count on current stack
1360 // of original IRP.
1361 //
1362
1363 nextIrpStack->Parameters.Others.Argument1 = (PVOID)(ULONG_PTR) irpCount;
1364
1365 for (i = 0; i < irpCount; i++) {
1366
1367 PIRP newIrp;
1368 PIO_STACK_LOCATION newIrpStack;
1369
1370 //
1371 // Allocate new IRP.
1372 //
1373
1374 newIrp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
1375
1376 if (newIrp == NULL) {
1377
1378 DebugPrint((1,"ScsiClassSplitRequest: Can't allocate Irp\n"));
1379
1380 //
1381 // If an Irp can't be allocated then the original request cannot
1382 // be executed. If this is the first request then just fail the
1383 // original request; otherwise just return. When the pending
1384 // requests complete, they will complete the original request.
1385 // In either case set the IRP status to failure.
1386 //
1387
1388 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
1389 Irp->IoStatus.Information = 0;
1390
1391 if (i == 0) {
1392 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1393 }
1394
1395 return;
1396 }
1397
1398 DebugPrint((2, "ScsiClassSplitRequest: New IRP %lx\n", newIrp));
1399
1400 //
1401 // Write MDL address to new IRP. In the port driver the SRB data
1402 // buffer field is used as an offset into the MDL, so the same MDL
1403 // can be used for each partial transfer. This saves having to build
1404 // a new MDL for each partial transfer.
1405 //
1406
1407 newIrp->MdlAddress = Irp->MdlAddress;
1408
1409 //
1410 // At this point there is no current stack. IoSetNextIrpStackLocation
1411 // will make the first stack location the current stack so that the
1412 // SRB address can be written there.
1413 //
1414
1415 IoSetNextIrpStackLocation(newIrp);
1416 newIrpStack = IoGetCurrentIrpStackLocation(newIrp);
1417
1418 newIrpStack->MajorFunction = currentIrpStack->MajorFunction;
1419 newIrpStack->Parameters.Read.Length = dataLength;
1420 newIrpStack->Parameters.Read.ByteOffset = startingOffset;
1421 newIrpStack->DeviceObject = DeviceObject;
1422
1423 //
1424 // Build SRB and CDB.
1425 //
1426
1427 ScsiClassBuildRequest(DeviceObject, newIrp);
1428
1429 //
1430 // Adjust SRB for this partial transfer.
1431 //
1432
1433 newIrpStack = IoGetNextIrpStackLocation(newIrp);
1434
1435 srb = newIrpStack->Parameters.Others.Argument1;
1436 srb->DataBuffer = dataBuffer;
1437
1438 //
1439 // Write original IRP address to new IRP.
1440 //
1441
1442 newIrp->AssociatedIrp.MasterIrp = Irp;
1443
1444 //
1445 // Set the completion routine to ScsiClassIoCompleteAssociated.
1446 //
1447
1448 IoSetCompletionRoutine(newIrp,
1449 ScsiClassIoCompleteAssociated,
1450 srb,
1451 TRUE,
1452 TRUE,
1453 TRUE);
1454
1455 //
1456 // Call port driver with new request.
1457 //
1458
1459 IoCallDriver(deviceExtension->PortDeviceObject, newIrp);
1460
1461 //
1462 // Set up for next request.
1463 //
1464
1465 dataBuffer = (PCHAR)dataBuffer + MaximumBytes;
1466
1467 transferByteCount -= MaximumBytes;
1468
1469 if (transferByteCount > MaximumBytes) {
1470
1471 dataLength = MaximumBytes;
1472
1473 } else {
1474
1475 dataLength = transferByteCount;
1476 }
1477
1478 //
1479 // Adjust disk byte offset.
1480 //
1481
1482 startingOffset.QuadPart = startingOffset.QuadPart + MaximumBytes;
1483 }
1484
1485 return;
1486
1487 } // end ScsiClassSplitRequest()
1488
1489
1490 NTSTATUS
1491 NTAPI
1492 ScsiClassIoComplete(
1493 IN PDEVICE_OBJECT DeviceObject,
1494 IN PIRP Irp,
1495 IN PVOID Context
1496 )
1497
1498 /*++
1499
1500 Routine Description:
1501
1502 This routine executes when the port driver has completed a request.
1503 It looks at the SRB status in the completing SRB and if not success
1504 it checks for valid request sense buffer information. If valid, the
1505 info is used to update status with more precise message of type of
1506 error. This routine deallocates the SRB.
1507
1508 Arguments:
1509
1510 DeviceObject - Supplies the device object which represents the logical
1511 unit.
1512
1513 Irp - Supplies the Irp which has completed.
1514
1515 Context - Supplies a pointer to the SRB.
1516
1517 Return Value:
1518
1519 NT status
1520
1521 --*/
1522
1523 {
1524 PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
1525 PSCSI_REQUEST_BLOCK srb = Context;
1526 PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
1527 NTSTATUS status;
1528 BOOLEAN retry;
1529
1530 ASSERT(*(PULONG)deviceExtension != '2slc');
1531
1532 //
1533 // Check SRB status for success of completing request.
1534 //
1535
1536 if (SRB_STATUS(srb->SrbStatus) != SRB_STATUS_SUCCESS) {
1537
1538 DebugPrint((2,"ScsiClassIoComplete: IRP %lx, SRB %lx\n", Irp, srb));
1539
1540 //
1541 // Release the queue if it is frozen.
1542 //
1543
1544 if (srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) {
1545 ScsiClassReleaseQueue(DeviceObject);
1546 }
1547
1548 retry = ScsiClassInterpretSenseInfo(
1549 DeviceObject,
1550 srb,
1551 irpStack->MajorFunction,
1552 irpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL ? irpStack->Parameters.DeviceIoControl.IoControlCode : 0,
1553 MAXIMUM_RETRIES - PtrToUlong(irpStack->Parameters.Others.Argument4),
1554 &status);
1555
1556 //
1557 // If the status is verified required and the this request
1558 // should bypass verify required then retry the request.
1559 //
1560
1561 if (irpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME &&
1562 status == STATUS_VERIFY_REQUIRED) {
1563
1564 status = STATUS_IO_DEVICE_ERROR;
1565 retry = TRUE;
1566 }
1567
1568 if (retry && (irpStack->Parameters.Others.Argument4 = (PVOID)((ULONG_PTR)irpStack->Parameters.Others.Argument4-1))) {
1569
1570 //
1571 // Retry request.
1572 //
1573
1574 DebugPrint((1, "Retry request %lx\n", Irp));
1575 RetryRequest(DeviceObject, Irp, srb, FALSE);
1576 return STATUS_MORE_PROCESSING_REQUIRED;
1577 }
1578 } else {
1579
1580 //
1581 // Set status for successful request.
1582 //
1583
1584 status = STATUS_SUCCESS;
1585
1586 } // end if (SRB_STATUS(srb->SrbStatus) ...
1587
1588 //
1589 // Return SRB to list.
1590 //
1591
1592 ExFreeToNPagedLookasideList(&deviceExtension->SrbLookasideListHead,
1593 srb);
1594
1595 //
1596 // Set status in completing IRP.
1597 //
1598
1599 Irp->IoStatus.Status = status;
1600 if ((NT_SUCCESS(status)) && (Irp->Flags & IRP_PAGING_IO)) {
1601 ASSERT(Irp->IoStatus.Information);
1602 }
1603
1604 //
1605 // Set the hard error if necessary.
1606 //
1607
1608 if (!NT_SUCCESS(status) && IoIsErrorUserInduced(status)) {
1609
1610 //
1611 // Store DeviceObject for filesystem, and clear
1612 // in IoStatus.Information field.
1613 //
1614
1615 IoSetHardErrorOrVerifyDevice(Irp, DeviceObject);
1616 Irp->IoStatus.Information = 0;
1617 }
1618
1619 //
1620 // If pending has be returned for this irp then mark the current stack as
1621 // pending.
1622 //
1623
1624 if (Irp->PendingReturned) {
1625 IoMarkIrpPending(Irp);
1626 }
1627
1628 if (deviceExtension->ClassStartIo) {
1629 if (irpStack->MajorFunction != IRP_MJ_DEVICE_CONTROL) {
1630 IoStartNextPacket(DeviceObject, FALSE);
1631 }
1632 }
1633
1634 return status;
1635
1636 } // end ScsiClassIoComplete()
1637
1638
1639 NTSTATUS
1640 NTAPI
1641 ScsiClassIoCompleteAssociated(
1642 IN PDEVICE_OBJECT DeviceObject,
1643 IN PIRP Irp,
1644 IN PVOID Context
1645 )
1646
1647 /*++
1648
1649 Routine Description:
1650
1651 This routine executes when the port driver has completed a request.
1652 It looks at the SRB status in the completing SRB and if not success
1653 it checks for valid request sense buffer information. If valid, the
1654 info is used to update status with more precise message of type of
1655 error. This routine deallocates the SRB. This routine is used for
1656 requests which were build by split request. After it has processed
1657 the request it decrements the Irp count in the master Irp. If the
1658 count goes to zero then the master Irp is completed.
1659
1660 Arguments:
1661
1662 DeviceObject - Supplies the device object which represents the logical
1663 unit.
1664
1665 Irp - Supplies the Irp which has completed.
1666
1667 Context - Supplies a pointer to the SRB.
1668
1669 Return Value:
1670
1671 NT status
1672
1673 --*/
1674
1675 {
1676 PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
1677 PSCSI_REQUEST_BLOCK srb = Context;
1678 PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
1679 PIRP originalIrp = Irp->AssociatedIrp.MasterIrp;
1680 LONG irpCount;
1681 NTSTATUS status;
1682 BOOLEAN retry;
1683
1684 ASSERT(*(PULONG)deviceExtension != '2slc');
1685
1686 //
1687 // Check SRB status for success of completing request.
1688 //
1689
1690 if (SRB_STATUS(srb->SrbStatus) != SRB_STATUS_SUCCESS) {
1691
1692 DebugPrint((2,"ScsiClassIoCompleteAssociated: IRP %lx, SRB %lx", Irp, srb));
1693
1694 //
1695 // Release the queue if it is frozen.
1696 //
1697
1698 if (srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) {
1699 ScsiClassReleaseQueue(DeviceObject);
1700 }
1701
1702 retry = ScsiClassInterpretSenseInfo(
1703 DeviceObject,
1704 srb,
1705 irpStack->MajorFunction,
1706 irpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL ? irpStack->Parameters.DeviceIoControl.IoControlCode : 0,
1707 MAXIMUM_RETRIES - PtrToUlong(irpStack->Parameters.Others.Argument4),
1708 &status);
1709
1710 //
1711 // If the status is verified required and the this request
1712 // should bypass verify required then retry the request.
1713 //
1714
1715 if (irpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME &&
1716 status == STATUS_VERIFY_REQUIRED) {
1717
1718 status = STATUS_IO_DEVICE_ERROR;
1719 retry = TRUE;
1720 }
1721
1722 if (retry && (irpStack->Parameters.Others.Argument4 = (PVOID)((ULONG_PTR)irpStack->Parameters.Others.Argument4-1))) {
1723
1724 //
1725 // Retry request. If the class driver has supplied a StartIo,
1726 // call it directly for retries.
1727 //
1728
1729 DebugPrint((1, "Retry request %lx\n", Irp));
1730
1731 /*
1732 if (!deviceExtension->ClassStartIo) {
1733 RetryRequest(DeviceObject, Irp, srb, TRUE);
1734 } else {
1735 deviceExtension->ClassStartIo(DeviceObject, Irp);
1736 }
1737 */
1738
1739 RetryRequest(DeviceObject, Irp, srb, TRUE);
1740
1741 return STATUS_MORE_PROCESSING_REQUIRED;
1742 }
1743
1744
1745
1746 } else {
1747
1748 //
1749 // Set status for successful request.
1750 //
1751
1752 status = STATUS_SUCCESS;
1753
1754 } // end if (SRB_STATUS(srb->SrbStatus) ...
1755
1756 //
1757 // Return SRB to list.
1758 //
1759
1760 ExFreeToNPagedLookasideList(&deviceExtension->SrbLookasideListHead,
1761 srb);
1762
1763 //
1764 // Set status in completing IRP.
1765 //
1766
1767 Irp->IoStatus.Status = status;
1768
1769 DebugPrint((2, "ScsiClassIoCompleteAssociated: Partial xfer IRP %lx\n", Irp));
1770
1771 //
1772 // Get next stack location. This original request is unused
1773 // except to keep track of the completing partial IRPs so the
1774 // stack location is valid.
1775 //
1776
1777 irpStack = IoGetNextIrpStackLocation(originalIrp);
1778
1779 //
1780 // Update status only if error so that if any partial transfer
1781 // completes with error, then the original IRP will return with
1782 // error. If any of the asynchronous partial transfer IRPs fail,
1783 // with an error then the original IRP will return 0 bytes transfered.
1784 // This is an optimization for successful transfers.
1785 //
1786
1787 if (!NT_SUCCESS(status)) {
1788
1789 originalIrp->IoStatus.Status = status;
1790 originalIrp->IoStatus.Information = 0;
1791
1792 //
1793 // Set the hard error if necessary.
1794 //
1795
1796 if (IoIsErrorUserInduced(status)) {
1797
1798 //
1799 // Store DeviceObject for filesystem.
1800 //
1801
1802 IoSetHardErrorOrVerifyDevice(originalIrp, DeviceObject);
1803 }
1804 }
1805
1806 //
1807 // Decrement and get the count of remaining IRPs.
1808 //
1809
1810 irpCount = InterlockedDecrement((PLONG)&irpStack->Parameters.Others.Argument1);
1811
1812 DebugPrint((2, "ScsiClassIoCompleteAssociated: Partial IRPs left %d\n",
1813 irpCount));
1814
1815 //
1816 // Old bug could cause irp count to negative
1817 //
1818
1819 ASSERT(irpCount >= 0);
1820
1821 if (irpCount == 0) {
1822
1823 //
1824 // All partial IRPs have completed.
1825 //
1826
1827 DebugPrint((2,
1828 "ScsiClassIoCompleteAssociated: All partial IRPs complete %lx\n",
1829 originalIrp));
1830
1831 IoCompleteRequest(originalIrp, IO_DISK_INCREMENT);
1832
1833 //
1834 // If the class driver has supplied a startio, start the
1835 // next request.
1836 //
1837
1838 if (deviceExtension->ClassStartIo) {
1839 IoStartNextPacket(DeviceObject, FALSE);
1840 }
1841 }
1842
1843 //
1844 // Deallocate IRP and indicate the I/O system should not attempt any more
1845 // processing.
1846 //
1847
1848 IoFreeIrp(Irp);
1849 return STATUS_MORE_PROCESSING_REQUIRED;
1850
1851 } // end ScsiClassIoCompleteAssociated()
1852
1853
1854 NTSTATUS
1855 NTAPI
1856 ScsiClassSendSrbSynchronous(
1857 PDEVICE_OBJECT DeviceObject,
1858 PSCSI_REQUEST_BLOCK Srb,
1859 PVOID BufferAddress,
1860 ULONG BufferLength,
1861 BOOLEAN WriteToDevice
1862 )
1863
1864 /*++
1865
1866 Routine Description:
1867
1868 This routine is called by SCSI device controls to complete an
1869 SRB and send it to the port driver synchronously (ie wait for
1870 completion). The CDB is already completed along with the SRB CDB
1871 size and request timeout value.
1872
1873 Arguments:
1874
1875 DeviceObject - Supplies the device object which represents the logical
1876 unit.
1877
1878 Srb - Supplies a partially initialized SRB. The SRB cannot come from zone.
1879
1880 BufferAddress - Supplies the address of the buffer.
1881
1882 BufferLength - Supplies the length in bytes of the buffer.
1883
1884 WriteToDevice - Indicates the data should be transfer to the device.
1885
1886 Return Value:
1887
1888 Nt status indicating the final results of the operation.
1889
1890 --*/
1891
1892 {
1893 PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
1894 IO_STATUS_BLOCK ioStatus;
1895 ULONG controlType, mjFunction;
1896 PIRP irp;
1897 PIO_STACK_LOCATION irpStack;
1898 KEVENT event;
1899 PUCHAR senseInfoBuffer;
1900 ULONG retryCount = MAXIMUM_RETRIES;
1901 NTSTATUS status;
1902 BOOLEAN retry;
1903 LARGE_INTEGER dummy;
1904
1905 PAGED_CODE();
1906
1907 ASSERT(*(PULONG)deviceExtension != '2slc');
1908
1909 dummy.QuadPart = 0;
1910
1911 //
1912 // Write length to SRB.
1913 //
1914
1915 Srb->Length = SCSI_REQUEST_BLOCK_SIZE;
1916
1917 //
1918 // Set SCSI bus address.
1919 //
1920
1921 Srb->PathId = deviceExtension->PathId;
1922 Srb->TargetId = deviceExtension->TargetId;
1923 Srb->Lun = deviceExtension->Lun;
1924 Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
1925
1926 //
1927 // NOTICE: The SCSI-II specification indicates that this field should be
1928 // zero; however, some target controllers ignore the logical unit number
1929 // in the IDENTIFY message and only look at the logical unit number field
1930 // in the CDB.
1931 //
1932
1933 Srb->Cdb[1] |= deviceExtension->Lun << 5;
1934
1935 //
1936 // Enable auto request sense.
1937 //
1938
1939 Srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE;
1940
1941 //
1942 // Sense buffer is in aligned nonpaged pool.
1943 //
1944
1945 senseInfoBuffer = ExAllocatePool(NonPagedPoolCacheAligned, SENSE_BUFFER_SIZE);
1946
1947 if (senseInfoBuffer == NULL) {
1948
1949 DebugPrint((1,
1950 "ScsiClassSendSrbSynchronous: Can't allocate request sense buffer\n"));
1951 return(STATUS_INSUFFICIENT_RESOURCES);
1952 }
1953
1954 Srb->SenseInfoBuffer = senseInfoBuffer;
1955 Srb->DataBuffer = BufferAddress;
1956
1957 //
1958 // Start retries here.
1959 //
1960
1961 retry:
1962
1963 //
1964 // Set the event object to the unsignaled state.
1965 // It will be used to signal request completion.
1966 //
1967
1968 KeInitializeEvent(&event, NotificationEvent, FALSE);
1969
1970 //
1971 // Set controlType and Srb direction flags.
1972 //
1973
1974 if (BufferAddress != NULL) {
1975
1976 if (WriteToDevice) {
1977
1978 controlType = IOCTL_SCSI_EXECUTE_OUT;
1979 Srb->SrbFlags = SRB_FLAGS_DATA_OUT;
1980 mjFunction = IRP_MJ_WRITE;
1981
1982 } else {
1983
1984 controlType = IOCTL_SCSI_EXECUTE_IN;
1985 Srb->SrbFlags = SRB_FLAGS_DATA_IN;
1986 mjFunction = IRP_MJ_READ;
1987 }
1988
1989 } else {
1990
1991 BufferLength = 0;
1992 controlType = IOCTL_SCSI_EXECUTE_NONE;
1993 Srb->SrbFlags = SRB_FLAGS_NO_DATA_TRANSFER;
1994 mjFunction = IRP_MJ_FLUSH_BUFFERS;
1995 }
1996
1997 //
1998 // Build device I/O control request with data transfer.
1999 //
2000 irp = IoBuildAsynchronousFsdRequest(
2001 mjFunction,
2002 deviceExtension->DeviceObject,
2003 BufferAddress,
2004 (BufferAddress) ? BufferLength : 0,
2005 &dummy,
2006 &ioStatus);
2007
2008 if (irp == NULL) {
2009 ExFreePool(senseInfoBuffer);
2010 DebugPrint((1, "ScsiClassSendSrbSynchronous: Can't allocate Irp\n"));
2011 return(STATUS_INSUFFICIENT_RESOURCES);
2012 }
2013
2014 // Set event field
2015 irp->UserEvent = &event;
2016
2017 //
2018 // Disable synchronous transfer for these requests.
2019 //
2020
2021 Srb->SrbFlags |= SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
2022
2023 //
2024 // Set the transfer length.
2025 //
2026
2027 Srb->DataTransferLength = BufferLength;
2028
2029 //
2030 // Zero out status.
2031 //
2032
2033 Srb->ScsiStatus = Srb->SrbStatus = 0;
2034 Srb->NextSrb = 0;
2035
2036 // Set completion routine
2037 IoSetCompletionRoutine(
2038 irp,
2039 ClassCompletionRoutine,
2040 NULL,
2041 TRUE,
2042 TRUE,
2043 TRUE);
2044
2045 //
2046 // Get next stack location.
2047 //
2048
2049 irpStack = IoGetNextIrpStackLocation(irp);
2050
2051 irpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
2052 irpStack->Parameters.DeviceIoControl.IoControlCode = controlType;
2053
2054 //
2055 // Set up SRB for execute scsi request. Save SRB address in next stack
2056 // for the port driver.
2057 //
2058
2059 irpStack->Parameters.Scsi.Srb = Srb;
2060
2061 //
2062 // Set up IRP Address.
2063 //
2064
2065 Srb->OriginalRequest = irp;
2066
2067 //
2068 // Call the port driver with the request and wait for it to complete.
2069 //
2070
2071 status = IoCallDriver(deviceExtension->PortDeviceObject, irp);
2072
2073 if (status == STATUS_PENDING) {
2074 KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, NULL);
2075 }
2076
2077 //
2078 // Check that request completed without error.
2079 //
2080
2081 if (SRB_STATUS(Srb->SrbStatus) != SRB_STATUS_SUCCESS) {
2082
2083 //
2084 // Release the queue if it is frozen.
2085 //
2086
2087 if (Srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) {
2088 ScsiClassReleaseQueue(DeviceObject);
2089 }
2090
2091 //
2092 // Update status and determine if request should be retried.
2093 //
2094
2095 retry = ScsiClassInterpretSenseInfo(DeviceObject,
2096 Srb,
2097 IRP_MJ_SCSI,
2098 0,
2099 MAXIMUM_RETRIES - retryCount,
2100 &status);
2101
2102 if (retry) {
2103
2104 if ((status == STATUS_DEVICE_NOT_READY && ((PSENSE_DATA) senseInfoBuffer)
2105 ->AdditionalSenseCode == SCSI_ADSENSE_LUN_NOT_READY) ||
2106 SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_SELECTION_TIMEOUT) {
2107
2108 LARGE_INTEGER delay;
2109
2110 //
2111 // Delay for 2 seconds.
2112 //
2113
2114 delay.QuadPart = (LONGLONG)( - 10 * 1000 * 1000 * 2 );
2115
2116 //
2117 // Stall for a while to let the controller spinup.
2118 //
2119
2120 KeDelayExecutionThread(KernelMode,
2121 FALSE,
2122 &delay);
2123
2124 }
2125
2126 //
2127 // If retries are not exhausted then retry this operation.
2128 //
2129
2130 if (retryCount--) {
2131 goto retry;
2132 }
2133 }
2134
2135 } else {
2136
2137 status = STATUS_SUCCESS;
2138 }
2139
2140 ExFreePool(senseInfoBuffer);
2141 return status;
2142
2143 } // end ScsiClassSendSrbSynchronous()
2144
2145
2146 BOOLEAN
2147 NTAPI
2148 ScsiClassInterpretSenseInfo(
2149 IN PDEVICE_OBJECT DeviceObject,
2150 IN PSCSI_REQUEST_BLOCK Srb,
2151 IN UCHAR MajorFunctionCode,
2152 IN ULONG IoDeviceCode,
2153 IN ULONG RetryCount,
2154 OUT NTSTATUS *Status
2155 )
2156
2157 /*++
2158
2159 Routine Description:
2160
2161 This routine interprets the data returned from the SCSI
2162 request sense. It determines the status to return in the
2163 IRP and whether this request can be retried.
2164
2165 Arguments:
2166
2167 DeviceObject - Supplies the device object associated with this request.
2168
2169 Srb - Supplies the scsi request block which failed.
2170
2171 MajorFunctionCode - Supplies the function code to be used for logging.
2172
2173 IoDeviceCode - Supplies the device code to be used for logging.
2174
2175 Status - Returns the status for the request.
2176
2177 Return Value:
2178
2179 BOOLEAN TRUE: Drivers should retry this request.
2180 FALSE: Drivers should not retry this request.
2181
2182 --*/
2183
2184 {
2185 PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
2186 PDEVICE_EXTENSION physicalExtension = deviceExtension->PhysicalDevice->DeviceExtension;
2187 PSENSE_DATA senseBuffer = Srb->SenseInfoBuffer;
2188 BOOLEAN retry = TRUE;
2189 BOOLEAN logError = FALSE;
2190 ULONG badSector = 0;
2191 ULONG uniqueId = 0;
2192 NTSTATUS logStatus;
2193 ULONG readSector;
2194 ULONG index;
2195 PIO_ERROR_LOG_PACKET errorLogEntry;
2196 #if DBG
2197 ULONG i;
2198 #endif
2199
2200 ASSERT(*(PULONG)deviceExtension != '2slc');
2201
2202 //
2203 // Check that request sense buffer is valid.
2204 //
2205
2206 #if DBG
2207 DebugPrint((3, "Opcode %x\nParameters: ",Srb->Cdb[0]));
2208 for (i = 1; i < 12; i++) {
2209 DebugPrint((3,"%x ",Srb->Cdb[i]));
2210 }
2211 DebugPrint((3,"\n"));
2212 #endif
2213
2214 if (Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID &&
2215 Srb->SenseInfoBufferLength >= FIELD_OFFSET(SENSE_DATA, CommandSpecificInformation)) {
2216
2217 DebugPrint((1,"ScsiClassInterpretSenseInfo: Error code is %x\n",
2218 senseBuffer->ErrorCode));
2219 DebugPrint((1,"ScsiClassInterpretSenseInfo: Sense key is %x\n",
2220 senseBuffer->SenseKey));
2221 DebugPrint((1, "ScsiClassInterpretSenseInfo: Additional sense code is %x\n",
2222 senseBuffer->AdditionalSenseCode));
2223 DebugPrint((1, "ScsiClassInterpretSenseInfo: Additional sense code qualifier is %x\n",
2224 senseBuffer->AdditionalSenseCodeQualifier));
2225
2226 //
2227 // Zero the additional sense code and additional sense code qualifier
2228 // if they were not returned by the device.
2229 //
2230
2231 readSector = senseBuffer->AdditionalSenseLength +
2232 FIELD_OFFSET(SENSE_DATA, AdditionalSenseLength);
2233
2234 if (readSector > Srb->SenseInfoBufferLength) {
2235 readSector = Srb->SenseInfoBufferLength;
2236 }
2237
2238 if (readSector <= FIELD_OFFSET(SENSE_DATA, AdditionalSenseCode)) {
2239 senseBuffer->AdditionalSenseCode = 0;
2240 }
2241
2242 if (readSector <= FIELD_OFFSET(SENSE_DATA, AdditionalSenseCodeQualifier)) {
2243 senseBuffer->AdditionalSenseCodeQualifier = 0;
2244 }
2245
2246 switch (senseBuffer->SenseKey & 0xf) {
2247
2248 case SCSI_SENSE_NOT_READY:
2249
2250 DebugPrint((1,"ScsiClassInterpretSenseInfo: Device not ready\n"));
2251 *Status = STATUS_DEVICE_NOT_READY;
2252
2253 switch (senseBuffer->AdditionalSenseCode) {
2254
2255 case SCSI_ADSENSE_LUN_NOT_READY:
2256
2257 DebugPrint((1,"ScsiClassInterpretSenseInfo: Lun not ready\n"));
2258
2259 switch (senseBuffer->AdditionalSenseCodeQualifier) {
2260
2261 case SCSI_SENSEQ_BECOMING_READY:
2262
2263 DebugPrint((1, "ScsiClassInterpretSenseInfo:"
2264 " In process of becoming ready\n"));
2265 break;
2266
2267 case SCSI_SENSEQ_MANUAL_INTERVENTION_REQUIRED:
2268
2269 DebugPrint((1, "ScsiClassInterpretSenseInfo:"
2270 " Manual intervention required\n"));
2271 *Status = STATUS_NO_MEDIA_IN_DEVICE;
2272 retry = FALSE;
2273 break;
2274
2275 case SCSI_SENSEQ_FORMAT_IN_PROGRESS:
2276
2277 DebugPrint((1, "ScsiClassInterpretSenseInfo: Format in progress\n"));
2278 retry = FALSE;
2279 break;
2280
2281 case SCSI_SENSEQ_INIT_COMMAND_REQUIRED:
2282
2283 default:
2284
2285 DebugPrint((1, "ScsiClassInterpretSenseInfo:"
2286 " Initializing command required\n"));
2287
2288 //
2289 // This sense code/additional sense code
2290 // combination may indicate that the device
2291 // needs to be started. Send an start unit if this
2292 // is a disk device.
2293 //
2294
2295 if (deviceExtension->DeviceFlags & DEV_SAFE_START_UNIT) {
2296 StartUnit(DeviceObject);
2297 }
2298
2299 break;
2300
2301 } // end switch (senseBuffer->AdditionalSenseCodeQualifier)
2302
2303 break;
2304
2305 case SCSI_ADSENSE_NO_MEDIA_IN_DEVICE:
2306
2307 DebugPrint((1,
2308 "ScsiClassInterpretSenseInfo:"
2309 " No Media in device.\n"));
2310 *Status = STATUS_NO_MEDIA_IN_DEVICE;
2311 retry = FALSE;
2312
2313 //
2314 // signal autorun that there isn't any media in the device
2315 //
2316
2317 if((deviceExtension->MediaChangeEvent != NULL)&&
2318 (!deviceExtension->MediaChangeNoMedia)) {
2319 KeSetEvent(deviceExtension->MediaChangeEvent,
2320 (KPRIORITY) 0,
2321 FALSE);
2322 DebugPrint((0, "ScsiClassInterpretSenseInfo:"
2323 "Detected No Media In Device "
2324 "[irp = 0x%lx]\n", Srb->OriginalRequest));
2325 deviceExtension->MediaChangeNoMedia = TRUE;
2326 }
2327
2328 break;
2329 } // end switch (senseBuffer->AdditionalSenseCode)
2330
2331 break;
2332
2333 case SCSI_SENSE_DATA_PROTECT:
2334
2335 DebugPrint((1, "ScsiClassInterpretSenseInfo: Media write protected\n"));
2336 *Status = STATUS_MEDIA_WRITE_PROTECTED;
2337 retry = FALSE;
2338 break;
2339
2340 case SCSI_SENSE_MEDIUM_ERROR:
2341
2342 DebugPrint((1,"ScsiClassInterpretSenseInfo: Bad media\n"));
2343 *Status = STATUS_DEVICE_DATA_ERROR;
2344
2345 retry = FALSE;
2346 logError = TRUE;
2347 uniqueId = 256;
2348 logStatus = 0;//IO_ERR_BAD_BLOCK;
2349 break;
2350
2351 case SCSI_SENSE_HARDWARE_ERROR:
2352
2353 DebugPrint((1,"ScsiClassInterpretSenseInfo: Hardware error\n"));
2354 *Status = STATUS_IO_DEVICE_ERROR;
2355
2356 logError = TRUE;
2357 uniqueId = 257;
2358 logStatus = 0;//IO_ERR_CONTROLLER_ERROR;
2359
2360 break;
2361
2362 case SCSI_SENSE_ILLEGAL_REQUEST:
2363
2364 DebugPrint((1, "ScsiClassInterpretSenseInfo: Illegal SCSI request\n"));
2365 *Status = STATUS_INVALID_DEVICE_REQUEST;
2366
2367 switch (senseBuffer->AdditionalSenseCode) {
2368
2369 case SCSI_ADSENSE_ILLEGAL_COMMAND:
2370 DebugPrint((1, "ScsiClassInterpretSenseInfo: Illegal command\n"));
2371 retry = FALSE;
2372 break;
2373
2374 case SCSI_ADSENSE_ILLEGAL_BLOCK:
2375 DebugPrint((1, "ScsiClassInterpretSenseInfo: Illegal block address\n"));
2376 *Status = STATUS_NONEXISTENT_SECTOR;
2377 retry = FALSE;
2378 break;
2379
2380 case SCSI_ADSENSE_INVALID_LUN:
2381 DebugPrint((1,"ScsiClassInterpretSenseInfo: Invalid LUN\n"));
2382 *Status = STATUS_NO_SUCH_DEVICE;
2383 retry = FALSE;
2384 break;
2385
2386 case SCSI_ADSENSE_MUSIC_AREA:
2387 DebugPrint((1,"ScsiClassInterpretSenseInfo: Music area\n"));
2388 retry = FALSE;
2389 break;
2390
2391 case SCSI_ADSENSE_DATA_AREA:
2392 DebugPrint((1,"ScsiClassInterpretSenseInfo: Data area\n"));
2393 retry = FALSE;
2394 break;
2395
2396 case SCSI_ADSENSE_VOLUME_OVERFLOW:
2397 DebugPrint((1, "ScsiClassInterpretSenseInfo: Volume overflow\n"));
2398 retry = FALSE;
2399 break;
2400
2401 case SCSI_ADSENSE_INVALID_CDB:
2402 DebugPrint((1, "ScsiClassInterpretSenseInfo: Invalid CDB\n"));
2403
2404 //
2405 // Check if write cache enabled.
2406 //
2407
2408 if (deviceExtension->DeviceFlags & DEV_WRITE_CACHE) {
2409
2410 //
2411 // Assume FUA is not supported.
2412 //
2413
2414 deviceExtension->DeviceFlags &= ~DEV_WRITE_CACHE;
2415 retry = TRUE;
2416
2417 } else {
2418 retry = FALSE;
2419 }
2420
2421 break;
2422
2423 } // end switch (senseBuffer->AdditionalSenseCode)
2424
2425 break;
2426
2427 case SCSI_SENSE_UNIT_ATTENTION:
2428
2429 switch (senseBuffer->AdditionalSenseCode) {
2430 case SCSI_ADSENSE_MEDIUM_CHANGED:
2431 DebugPrint((1, "ScsiClassInterpretSenseInfo: Media changed\n"));
2432
2433 if(deviceExtension->MediaChangeEvent != NULL) {
2434
2435 KeSetEvent(deviceExtension->MediaChangeEvent,
2436 (KPRIORITY) 0,
2437 FALSE);
2438 DebugPrint((0, "ScsiClassInterpretSenseInfo:"
2439 "New Media Found - Setting MediaChanged event"
2440 " [irp = 0x%lx]\n", Srb->OriginalRequest));
2441 deviceExtension->MediaChangeNoMedia = FALSE;
2442
2443 }
2444 break;
2445
2446 case SCSI_ADSENSE_BUS_RESET:
2447 DebugPrint((1,"ScsiClassInterpretSenseInfo: Bus reset\n"));
2448 break;
2449
2450 default:
2451 DebugPrint((1,"ScsiClassInterpretSenseInfo: Unit attention\n"));
2452 break;
2453
2454 } // end switch (senseBuffer->AdditionalSenseCode)
2455
2456 if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA &&
2457 DeviceObject->Vpb->Flags & VPB_MOUNTED) {
2458
2459 //
2460 // Set bit to indicate that media may have changed
2461 // and volume needs verification.
2462 //
2463
2464 DeviceObject->Flags |= DO_VERIFY_VOLUME;
2465
2466 *Status = STATUS_VERIFY_REQUIRED;
2467 retry = FALSE;
2468
2469 } else {
2470
2471 *Status = STATUS_IO_DEVICE_ERROR;
2472
2473 }
2474
2475 //
2476 // A media change may have occured so increment the change
2477 // count for the physical device
2478 //
2479
2480 physicalExtension->MediaChangeCount++;
2481
2482 DebugPrint((2, "ScsiClassInterpretSenseInfo - Media change "
2483 "count for device %d is %d\n",
2484 physicalExtension->DeviceNumber,
2485 physicalExtension->MediaChangeCount));
2486
2487 break;
2488
2489 case SCSI_SENSE_ABORTED_COMMAND:
2490
2491 DebugPrint((1,"ScsiClassInterpretSenseInfo: Command aborted\n"));
2492 *Status = STATUS_IO_DEVICE_ERROR;
2493 break;
2494
2495 case SCSI_SENSE_RECOVERED_ERROR:
2496
2497 DebugPrint((1,"ScsiClassInterpretSenseInfo: Recovered error\n"));
2498 *Status = STATUS_SUCCESS;
2499 retry = FALSE;
2500 logError = TRUE;
2501 uniqueId = 258;
2502
2503 switch(senseBuffer->AdditionalSenseCode) {
2504 case SCSI_ADSENSE_SEEK_ERROR:
2505 case SCSI_ADSENSE_TRACK_ERROR:
2506 logStatus = 0;//IO_ERR_SEEK_ERROR;
2507 break;
2508
2509 case SCSI_ADSENSE_REC_DATA_NOECC:
2510 case SCSI_ADSENSE_REC_DATA_ECC:
2511 logStatus = 0;//IO_RECOVERED_VIA_ECC;
2512 break;
2513
2514 default:
2515 logStatus = 0;//IO_ERR_CONTROLLER_ERROR;
2516 break;
2517
2518 } // end switch(senseBuffer->AdditionalSenseCode)
2519
2520 if (senseBuffer->IncorrectLength) {
2521
2522 DebugPrint((1, "ScsiClassInterpretSenseInfo: Incorrect length detected.\n"));
2523 *Status = STATUS_INVALID_BLOCK_LENGTH ;
2524 }
2525
2526 break;
2527
2528 case SCSI_SENSE_NO_SENSE:
2529
2530 //
2531 // Check other indicators.
2532 //
2533
2534 if (senseBuffer->IncorrectLength) {
2535
2536 DebugPrint((1, "ScsiClassInterpretSenseInfo: Incorrect length detected.\n"));
2537 *Status = STATUS_INVALID_BLOCK_LENGTH ;
2538 retry = FALSE;
2539
2540 } else {
2541
2542 DebugPrint((1, "ScsiClassInterpretSenseInfo: No specific sense key\n"));
2543 *Status = STATUS_IO_DEVICE_ERROR;
2544 retry = TRUE;
2545 }
2546
2547 break;
2548
2549 default:
2550
2551 DebugPrint((1, "ScsiClassInterpretSenseInfo: Unrecognized sense code\n"));
2552 *Status = STATUS_IO_DEVICE_ERROR;
2553 break;
2554
2555 } // end switch (senseBuffer->SenseKey & 0xf)
2556
2557 //
2558 // Try to determine the bad sector from the inquiry data.
2559 //
2560
2561 if ((((PCDB)Srb->Cdb)->CDB10.OperationCode == SCSIOP_READ ||
2562 ((PCDB)Srb->Cdb)->CDB10.OperationCode == SCSIOP_VERIFY ||
2563 ((PCDB)Srb->Cdb)->CDB10.OperationCode == SCSIOP_WRITE)) {
2564
2565 for (index = 0; index < 4; index++) {
2566 badSector = (badSector << 8) | senseBuffer->Information[index];
2567 }
2568
2569 readSector = 0;
2570 for (index = 0; index < 4; index++) {
2571 readSector = (readSector << 8) | Srb->Cdb[index+2];
2572 }
2573
2574 index = (((PCDB)Srb->Cdb)->CDB10.TransferBlocksMsb << 8) |
2575 ((PCDB)Srb->Cdb)->CDB10.TransferBlocksLsb;
2576
2577 //
2578 // Make sure the bad sector is within the read sectors.
2579 //
2580
2581 if (!(badSector >= readSector && badSector < readSector + index)) {
2582 badSector = readSector;
2583 }
2584 }
2585
2586 } else {
2587
2588 //
2589 // Request sense buffer not valid. No sense information
2590 // to pinpoint the error. Return general request fail.
2591 //
2592
2593 DebugPrint((1,"ScsiClassInterpretSenseInfo: Request sense info not valid. SrbStatus %2x\n",
2594 SRB_STATUS(Srb->SrbStatus)));
2595 retry = TRUE;
2596
2597 switch (SRB_STATUS(Srb->SrbStatus)) {
2598 case SRB_STATUS_INVALID_LUN:
2599 case SRB_STATUS_INVALID_TARGET_ID:
2600 case SRB_STATUS_NO_DEVICE:
2601 case SRB_STATUS_NO_HBA:
2602 case SRB_STATUS_INVALID_PATH_ID:
2603 *Status = STATUS_NO_SUCH_DEVICE;
2604 retry = FALSE;
2605 break;
2606
2607 case SRB_STATUS_COMMAND_TIMEOUT:
2608 case SRB_STATUS_ABORTED:
2609 case SRB_STATUS_TIMEOUT:
2610
2611 //
2612 // Update the error count for the device.
2613 //
2614
2615 deviceExtension->ErrorCount++;
2616 *Status = STATUS_IO_TIMEOUT;
2617 break;
2618
2619 case SRB_STATUS_SELECTION_TIMEOUT:
2620 logError = TRUE;
2621 logStatus = 0;//IO_ERR_NOT_READY;
2622 uniqueId = 260;
2623 *Status = STATUS_DEVICE_NOT_CONNECTED;
2624 retry = FALSE;
2625 break;
2626
2627 case SRB_STATUS_DATA_OVERRUN:
2628 *Status = STATUS_DATA_OVERRUN;
2629 retry = FALSE;
2630 break;
2631
2632 case SRB_STATUS_PHASE_SEQUENCE_FAILURE:
2633
2634 //
2635 // Update the error count for the device.
2636 //
2637
2638 deviceExtension->ErrorCount++;
2639 *Status = STATUS_IO_DEVICE_ERROR;
2640
2641 //
2642 // If there was phase sequence error then limit the number of
2643 // retries.
2644 //
2645
2646 if (RetryCount > 1 ) {
2647 retry = FALSE;
2648 }
2649
2650 break;
2651
2652 case SRB_STATUS_REQUEST_FLUSHED:
2653
2654 //
2655 // If the status needs verification bit is set. Then set
2656 // the status to need verification and no retry; otherwise,
2657 // just retry the request.
2658 //
2659
2660 if (DeviceObject->Flags & DO_VERIFY_VOLUME ) {
2661
2662 *Status = STATUS_VERIFY_REQUIRED;
2663 retry = FALSE;
2664 } else {
2665 *Status = STATUS_IO_DEVICE_ERROR;
2666 }
2667
2668 break;
2669
2670 case SRB_STATUS_INVALID_REQUEST:
2671
2672 //
2673 // An invalid request was attempted.
2674 //
2675
2676 *Status = STATUS_INVALID_DEVICE_REQUEST;
2677 retry = FALSE;
2678 break;
2679
2680 case SRB_STATUS_UNEXPECTED_BUS_FREE:
2681 case SRB_STATUS_PARITY_ERROR:
2682
2683 //
2684 // Update the error count for the device.
2685 //
2686
2687 deviceExtension->ErrorCount++;
2688
2689 //
2690 // Fall through to below.
2691 //
2692
2693 case SRB_STATUS_BUS_RESET:
2694 *Status = STATUS_IO_DEVICE_ERROR;
2695 break;
2696
2697 case SRB_STATUS_ERROR:
2698
2699 *Status = STATUS_IO_DEVICE_ERROR;
2700 if (Srb->ScsiStatus == 0) {
2701
2702 //
2703 // This is some strange return code. Update the error
2704 // count for the device.
2705 //
2706
2707 deviceExtension->ErrorCount++;
2708
2709 } if (Srb->ScsiStatus == SCSISTAT_BUSY) {
2710
2711 *Status = STATUS_DEVICE_NOT_READY;
2712
2713 } if (Srb->ScsiStatus == SCSISTAT_RESERVATION_CONFLICT) {
2714
2715 *Status = STATUS_DEVICE_BUSY;
2716 retry = FALSE;
2717
2718 }
2719
2720 break;
2721
2722 default:
2723 logError = TRUE;
2724 logStatus = 0;//IO_ERR_CONTROLLER_ERROR;
2725 uniqueId = 259;
2726 *Status = STATUS_IO_DEVICE_ERROR;
2727 break;
2728
2729 }
2730
2731 //
2732 // If the error count has exceeded the error limit, then disable
2733 // any tagged queuing, multiple requests per lu queueing
2734 // and synchronous data transfers.
2735 //
2736
2737 if (deviceExtension->ErrorCount == 4) {
2738
2739 //
2740 // Clearing the no queue freeze flag prevents the port driver
2741 // from sending multiple requests per logical unit.
2742 //
2743
2744 deviceExtension->SrbFlags &= ~(SRB_FLAGS_QUEUE_ACTION_ENABLE |
2745 SRB_FLAGS_NO_QUEUE_FREEZE);
2746
2747 deviceExtension->SrbFlags |= SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
2748 DebugPrint((1, "ScsiClassInterpretSenseInfo: Too many errors disabling tagged queuing and synchronous data tranfers.\n"));
2749
2750 } else if (deviceExtension->ErrorCount == 8) {
2751
2752 //
2753 // If a second threshold is reached, disable disconnects.
2754 //
2755
2756 deviceExtension->SrbFlags |= SRB_FLAGS_DISABLE_DISCONNECT;
2757 DebugPrint((1, "ScsiClassInterpretSenseInfo: Too many errors disabling disconnects.\n"));
2758 }
2759 }
2760
2761 //
2762 // If there is a class specific error handler call it.
2763 //
2764
2765 if (deviceExtension->ClassError != NULL) {
2766
2767 deviceExtension->ClassError(DeviceObject,
2768 Srb,
2769 Status,
2770 &retry);
2771 }
2772
2773 //
2774 // Log an error if necessary.
2775 //
2776
2777 if (logError) {
2778
2779 errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(
2780 DeviceObject,
2781 sizeof(IO_ERROR_LOG_PACKET) + 5 * sizeof(ULONG));
2782
2783 if (errorLogEntry == NULL) {
2784
2785 //
2786 // Return if no packet could be allocated.
2787 //
2788
2789 return retry;
2790
2791 }
2792
2793 if (retry && RetryCount < MAXIMUM_RETRIES) {
2794 errorLogEntry->FinalStatus = STATUS_SUCCESS;
2795 } else {
2796 errorLogEntry->FinalStatus = *Status;
2797 }
2798
2799 //
2800 // Calculate the device offset if there is a geometry.
2801 //
2802
2803 if (deviceExtension->DiskGeometry != NULL) {
2804
2805 errorLogEntry->DeviceOffset.QuadPart = (LONGLONG) badSector;
2806 errorLogEntry->DeviceOffset = RtlExtendedIntegerMultiply(
2807 errorLogEntry->DeviceOffset,
2808 deviceExtension->DiskGeometry->Geometry.BytesPerSector);
2809 }
2810
2811 errorLogEntry->ErrorCode = logStatus;
2812 errorLogEntry->SequenceNumber = 0;
2813 errorLogEntry->MajorFunctionCode = MajorFunctionCode;
2814 errorLogEntry->IoControlCode = IoDeviceCode;
2815 errorLogEntry->RetryCount = (UCHAR) RetryCount;
2816 errorLogEntry->UniqueErrorValue = uniqueId;
2817 errorLogEntry->DumpDataSize = 6 * sizeof(ULONG);
2818 errorLogEntry->DumpData[0] = Srb->PathId;
2819 errorLogEntry->DumpData[1] = Srb->TargetId;
2820 errorLogEntry->DumpData[2] = Srb->Lun;
2821 errorLogEntry->DumpData[3] = 0;
2822 errorLogEntry->DumpData[4] = Srb->SrbStatus << 8 | Srb->ScsiStatus;
2823
2824 if (senseBuffer != NULL) {
2825 errorLogEntry->DumpData[5] = senseBuffer->SenseKey << 16 |
2826 senseBuffer->AdditionalSenseCode << 8 |
2827 senseBuffer->AdditionalSenseCodeQualifier;
2828
2829 }
2830
2831 //
2832 // Write the error log packet.
2833 //
2834
2835 IoWriteErrorLogEntry(errorLogEntry);
2836 }
2837
2838 return retry;
2839
2840 } // end ScsiClassInterpretSenseInfo()
2841
2842
2843 VOID
2844 NTAPI
2845 RetryRequest(
2846 PDEVICE_OBJECT DeviceObject,
2847 PIRP Irp,
2848 PSCSI_REQUEST_BLOCK Srb,
2849 BOOLEAN Associated
2850 )
2851
2852 /*++
2853
2854 Routine Description:
2855
2856 This routine reinitializes the necessary fields, and sends the request
2857 to the port driver.
2858
2859 Arguments:
2860
2861 DeviceObject - Supplies the device object associated with this request.
2862
2863 Irp - Supplies the request to be retried.
2864
2865 Srb - Supplies a Pointer to the SCSI request block to be retied.
2866
2867 Associated - Indicates this is an associated Irp created by split request.
2868
2869 Return Value:
2870
2871 None
2872
2873 --*/
2874
2875 {
2876 PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
2877 PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
2878 PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp);
2879 ULONG transferByteCount;
2880
2881 ASSERT(*(PULONG)deviceExtension != '2slc');
2882
2883 //
2884 // Determine the transfer count of the request. If this is a read or a
2885 // write then the transfer count is in the Irp stack. Otherwise assume
2886 // the MDL contains the correct length. If there is no MDL then the
2887 // transfer length must be zero.
2888 //
2889
2890 if (currentIrpStack->MajorFunction == IRP_MJ_READ ||
2891 currentIrpStack->MajorFunction == IRP_MJ_WRITE) {
2892
2893 transferByteCount = currentIrpStack->Parameters.Read.Length;
2894
2895 } else if (Irp->MdlAddress != NULL) {
2896
2897 //
2898 // Note this assumes that only read and write requests are spilt and
2899 // other request do not need to be. If the data buffer address in
2900 // the MDL and the SRB don't match then transfer length is most
2901 // likely incorrect.
2902 //
2903
2904 ASSERT(Srb->DataBuffer == MmGetMdlVirtualAddress(Irp->MdlAddress));
2905 transferByteCount = Irp->MdlAddress->ByteCount;
2906
2907 } else {
2908
2909 transferByteCount = 0;
2910 }
2911
2912 //
2913 // Reset byte count of transfer in SRB Extension.
2914 //
2915
2916 Srb->DataTransferLength = transferByteCount;
2917
2918 //
2919 // Zero SRB statuses.
2920 //
2921
2922 Srb->SrbStatus = Srb->ScsiStatus = 0;
2923
2924 //
2925 // Set the no disconnect flag, disable synchronous data transfers and
2926 // disable tagged queuing. This fixes some errors.
2927 //
2928
2929 Srb->SrbFlags |= SRB_FLAGS_DISABLE_DISCONNECT |
2930 SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
2931
2932 Srb->SrbFlags &= ~SRB_FLAGS_QUEUE_ACTION_ENABLE;
2933 Srb->QueueTag = SP_UNTAGGED;
2934
2935 //
2936 // Set up major SCSI function.
2937 //
2938
2939 nextIrpStack->MajorFunction = IRP_MJ_SCSI;
2940
2941 //
2942 // Save SRB address in next stack for port driver.
2943 //
2944
2945 nextIrpStack->Parameters.Scsi.Srb = Srb;
2946
2947 //
2948 // Set up IoCompletion routine address.
2949 //
2950
2951 if (Associated) {
2952
2953 IoSetCompletionRoutine(Irp, ScsiClassIoCompleteAssociated, Srb, TRUE, TRUE, TRUE);
2954
2955 } else {
2956
2957 IoSetCompletionRoutine(Irp, ScsiClassIoComplete, Srb, TRUE, TRUE, TRUE);
2958 }
2959
2960 //
2961 // Pass the request to the port driver.
2962 //
2963
2964 (VOID)IoCallDriver(deviceExtension->PortDeviceObject, Irp);
2965
2966 } // end RetryRequest()
2967
2968 VOID
2969 NTAPI
2970 ScsiClassBuildRequest(
2971 PDEVICE_OBJECT DeviceObject,
2972 PIRP Irp
2973 )
2974
2975 /*++
2976
2977 Routine Description:
2978
2979 This routine allocates and builds an Srb for a read or write request.
2980 The block address and length are supplied by the Irp. The retry count
2981 is stored in the current stack for use by ScsiClassIoComplete which
2982 processes these requests when they complete. The Irp is ready to be
2983 passed to the port driver when this routine returns.
2984
2985 Arguments:
2986
2987 DeviceObject - Supplies the device object associated with this request.
2988
2989 Irp - Supplies the request to be retried.
2990
2991 Note:
2992
2993 If the IRP is for a disk transfer, the byteoffset field
2994 will already have been adjusted to make it relative to
2995 the beginning of the disk.
2996
2997
2998 Return Value:
2999
3000 None.
3001
3002 --*/
3003
3004 {
3005 PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
3006 PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
3007 PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp);
3008 LARGE_INTEGER startingOffset = currentIrpStack->Parameters.Read.ByteOffset;
3009 PSCSI_REQUEST_BLOCK srb;
3010 PCDB cdb;
3011 ULONG logicalBlockAddress;
3012 USHORT transferBlocks;
3013
3014 ASSERT(*(PULONG)deviceExtension != '2slc');
3015
3016 //
3017 // Calculate relative sector address.
3018 //
3019
3020 logicalBlockAddress = (ULONG)(Int64ShrlMod32(startingOffset.QuadPart, deviceExtension->SectorShift));
3021
3022 //
3023 // Allocate an Srb.
3024 //
3025
3026 srb = ExAllocateFromNPagedLookasideList(&deviceExtension->SrbLookasideListHead);
3027
3028 srb->SrbFlags = 0;
3029
3030 //
3031 // Write length to SRB.
3032 //
3033
3034 srb->Length = SCSI_REQUEST_BLOCK_SIZE;
3035
3036 //
3037 // Set up IRP Address.
3038 //
3039
3040 srb->OriginalRequest = Irp;
3041
3042 //
3043 // Set up target ID and logical unit number.
3044 //
3045
3046 srb->PathId = deviceExtension->PathId;
3047 srb->TargetId = deviceExtension->TargetId;
3048 srb->Lun = deviceExtension->Lun;
3049 srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
3050 srb->DataBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress);
3051
3052 //
3053 // Save byte count of transfer in SRB Extension.
3054 //
3055
3056 srb->DataTransferLength = currentIrpStack->Parameters.Read.Length;
3057
3058 //
3059 // Initialize the queue actions field.
3060 //
3061
3062 srb->QueueAction = SRB_SIMPLE_TAG_REQUEST;
3063
3064 //
3065 // Queue sort key is Relative Block Address.
3066 //
3067
3068 srb->QueueSortKey = logicalBlockAddress;
3069
3070 //
3071 // Indicate auto request sense by specifying buffer and size.
3072 //
3073
3074 srb->SenseInfoBuffer = deviceExtension->SenseData;
3075 srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE;
3076
3077 //
3078 // Set timeout value of one unit per 64k bytes of data.
3079 //
3080
3081 srb->TimeOutValue = ((srb->DataTransferLength + 0xFFFF) >> 16) *
3082 deviceExtension->TimeOutValue;
3083
3084 //
3085 // Zero statuses.
3086 //
3087
3088 srb->SrbStatus = srb->ScsiStatus = 0;
3089 srb->NextSrb = 0;
3090
3091 //
3092 // Indicate that 10-byte CDB's will be used.
3093 //
3094
3095 srb->CdbLength = 10;
3096
3097 //
3098 // Fill in CDB fields.
3099 //
3100
3101 cdb = (PCDB)srb->Cdb;
3102
3103 //
3104 // Zero 12 bytes for Atapi Packets
3105 //
3106
3107 RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
3108
3109 cdb->CDB10.LogicalUnitNumber = deviceExtension->Lun;
3110 transferBlocks = (USHORT)(currentIrpStack->Parameters.Read.Length >> deviceExtension->SectorShift);
3111
3112 //
3113 // Move little endian values into CDB in big endian format.
3114 //
3115
3116 cdb->CDB10.LogicalBlockByte0 = ((PFOUR_BYTE)&logicalBlockAddress)->Byte3;
3117 cdb->CDB10.LogicalBlockByte1 = ((PFOUR_BYTE)&logicalBlockAddress)->Byte2;
3118 cdb->CDB10.LogicalBlockByte2 = ((PFOUR_BYTE)&logicalBlockAddress)->Byte1;
3119 cdb->CDB10.LogicalBlockByte3 = ((PFOUR_BYTE)&logicalBlockAddress)->Byte0;
3120
3121 cdb->CDB10.TransferBlocksMsb = ((PFOUR_BYTE)&transferBlocks)->Byte1;
3122 cdb->CDB10.TransferBlocksLsb = ((PFOUR_BYTE)&transferBlocks)->Byte0;
3123
3124 //
3125 // Set transfer direction flag and Cdb command.
3126 //
3127
3128 if (currentIrpStack->MajorFunction == IRP_MJ_READ) {
3129
3130 DebugPrint((3, "ScsiClassBuildRequest: Read Command\n"));
3131
3132 srb->SrbFlags |= SRB_FLAGS_DATA_IN;
3133 cdb->CDB10.OperationCode = SCSIOP_READ;
3134
3135 } else {
3136
3137 DebugPrint((3, "ScsiClassBuildRequest: Write Command\n"));
3138
3139 srb->SrbFlags |= SRB_FLAGS_DATA_OUT;
3140 cdb->CDB10.OperationCode = SCSIOP_WRITE;
3141 }
3142
3143 //
3144 // If this is not a write-through request, then allow caching.
3145 //
3146
3147 if (!(currentIrpStack->Flags & SL_WRITE_THROUGH)) {
3148
3149 srb->SrbFlags |= SRB_FLAGS_ADAPTER_CACHE_ENABLE;
3150
3151 } else {
3152
3153 //
3154 // If write caching is enable then force media access in the
3155 // cdb.
3156 //
3157
3158 if (deviceExtension->DeviceFlags & DEV_WRITE_CACHE) {
3159 cdb->CDB10.ForceUnitAccess = TRUE;
3160 }
3161 }
3162
3163 //
3164 // Or in the default flags from the device object.
3165 //
3166
3167 srb->SrbFlags |= deviceExtension->SrbFlags;
3168
3169 //
3170 // Set up major SCSI function.
3171 //
3172
3173 nextIrpStack->MajorFunction = IRP_MJ_SCSI;
3174
3175 //
3176 // Save SRB address in next stack for port driver.
3177 //
3178
3179 nextIrpStack->Parameters.Scsi.Srb = srb;
3180
3181 //
3182 // Save retry count in current IRP stack.
3183 //
3184
3185 currentIrpStack->Parameters.Others.Argument4 = (PVOID)MAXIMUM_RETRIES;
3186
3187 //
3188 // Set up IoCompletion routine address.
3189 //
3190
3191 IoSetCompletionRoutine(Irp, ScsiClassIoComplete, srb, TRUE, TRUE, TRUE);
3192
3193 return;
3194
3195 } // end ScsiClassBuildRequest()
3196
3197 ULONG
3198 NTAPI
3199 ScsiClassModeSense(
3200 IN PDEVICE_OBJECT DeviceObject,
3201 IN PCHAR ModeSenseBuffer,
3202 IN ULONG Length,
3203 IN UCHAR PageMode
3204 )
3205
3206 /*++
3207
3208 Routine Description:
3209
3210 This routine sends a mode sense command to a target ID and returns
3211 when it is complete.
3212
3213 Arguments:
3214
3215 DeviceObject - Supplies the device object associated with this request.
3216
3217 ModeSenseBuffer - Supplies a buffer to store the sense data.
3218
3219 Length - Supplies the length in bytes of the mode sense buffer.
3220
3221 PageMode - Supplies the page or pages of mode sense data to be retrieved.
3222
3223 Return Value:
3224
3225 Length of the transferred data is returned.
3226
3227 --*/
3228 {
3229 PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
3230 PCDB cdb;
3231 SCSI_REQUEST_BLOCK srb;
3232 ULONG retries = 1;
3233 NTSTATUS status;
3234
3235 ASSERT(*(PULONG)deviceExtension != '2slc');
3236
3237 RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK));
3238
3239 //
3240 // Build the MODE SENSE CDB.
3241 //
3242
3243 srb.CdbLength = 6;
3244 cdb = (PCDB)srb.Cdb;
3245
3246 //
3247 // Set timeout value from device extension.
3248 //
3249
3250 srb.TimeOutValue = deviceExtension->TimeOutValue;
3251
3252 cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
3253 cdb->MODE_SENSE.PageCode = PageMode;
3254 cdb->MODE_SENSE.AllocationLength = (UCHAR)Length;
3255
3256 Retry:
3257
3258 status = ScsiClassSendSrbSynchronous(DeviceObject,
3259 &srb,
3260 ModeSenseBuffer,
3261 Length,
3262 FALSE);
3263
3264
3265 if (status == STATUS_VERIFY_REQUIRED) {
3266
3267 //
3268 // Routine ScsiClassSendSrbSynchronous does not retry requests returned with
3269 // this status. MODE SENSE commands should be retried anyway.
3270 //
3271
3272 if (retries--) {
3273
3274 //
3275 // Retry request.
3276 //
3277
3278 goto Retry;
3279 }
3280
3281 } else if (SRB_STATUS(srb.SrbStatus) == SRB_STATUS_DATA_OVERRUN) {
3282 status = STATUS_SUCCESS;
3283 }
3284
3285 if (NT_SUCCESS(status)) {
3286 return(srb.DataTransferLength);
3287 } else {
3288 return(0);
3289 }
3290
3291 } // end ScsiClassModeSense()
3292
3293
3294 PVOID
3295 NTAPI
3296 ScsiClassFindModePage(
3297 IN PCHAR ModeSenseBuffer,
3298 IN ULONG Length,
3299 IN UCHAR PageMode,
3300 IN BOOLEAN Use6Byte
3301 )
3302
3303 /*++
3304
3305 Routine Description:
3306
3307 This routine scans through the mode sense data and finds the requested
3308 mode sense page code.
3309
3310 Arguments:
3311 ModeSenseBuffer - Supplies a pointer to the mode sense data.
3312
3313 Length - Indicates the length of valid data.
3314
3315 PageMode - Supplies the page mode to be searched for.
3316
3317 Use6Byte - Indicates whether 6 or 10 byte mode sense was used.
3318
3319 Return Value:
3320
3321 A pointer to the the requested mode page. If the mode page was not found
3322 then NULL is return.
3323
3324 --*/
3325 {
3326 PUCHAR limit;
3327 ULONG parameterHeaderLength;
3328
3329 limit = (PUCHAR)ModeSenseBuffer + Length;
3330 parameterHeaderLength = (Use6Byte) ? sizeof(MODE_PARAMETER_HEADER) : sizeof(MODE_PARAMETER_HEADER10);
3331
3332
3333 //
3334 // Skip the mode select header and block descriptors.
3335 //
3336
3337 if (Length < parameterHeaderLength) {
3338 return(NULL);
3339 }
3340
3341
3342
3343 ModeSenseBuffer += parameterHeaderLength + ((Use6Byte) ? ((PMODE_PARAMETER_HEADER) ModeSenseBuffer)->BlockDescriptorLength :
3344 ((PMODE_PARAMETER_HEADER10) ModeSenseBuffer)->BlockDescriptorLength[1]);
3345
3346 //
3347 // ModeSenseBuffer now points at pages. Walk the pages looking for the
3348 // requested page until the limit is reached.
3349 //
3350
3351
3352 while ((PUCHAR)ModeSenseBuffer < limit) {
3353
3354 if (((PMODE_DISCONNECT_PAGE) ModeSenseBuffer)->PageCode == PageMode) {
3355 return(ModeSenseBuffer);
3356 }
3357
3358 //
3359 // Advance to the next page.
3360 //
3361
3362 ModeSenseBuffer += ((PMODE_DISCONNECT_PAGE) ModeSenseBuffer)->PageLength + 2;
3363 }
3364
3365 return(NULL);
3366 }
3367
3368 NTSTATUS
3369 NTAPI
3370 ScsiClassSendSrbAsynchronous(
3371 PDEVICE_OBJECT DeviceObject,
3372 PSCSI_REQUEST_BLOCK Srb,
3373 PIRP Irp,
3374 PVOID BufferAddress,
3375 ULONG BufferLength,
3376 BOOLEAN WriteToDevice
3377 )
3378 /*++
3379
3380 Routine Description:
3381
3382 This routine takes a partially built Srb and an Irp and sends it down to
3383 the port driver.
3384
3385 Arguments:
3386 DeviceObject - Supplies the device object for the original request.
3387
3388 Srb - Supplies a partially built ScsiRequestBlock. In particular, the
3389 CDB and the SRB timeout value must be filled in. The SRB must not be
3390 allocated from zone.
3391
3392 Irp - Supplies the requesting Irp.
3393
3394 BufferAddress - Supplies a pointer to the buffer to be transfered.
3395
3396 BufferLength - Supplies the length of data transfer.
3397
3398 WriteToDevice - Indicates the data transfer will be from system memory to
3399 device.
3400
3401 Return Value:
3402
3403 Returns STATUS_INSUFFICIENT_RESOURCES or the status of IoCallDriver.
3404
3405 --*/
3406 {
3407
3408 PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
3409 PIO_STACK_LOCATION irpStack;
3410
3411 PAGED_CODE();
3412
3413 ASSERT(*(PULONG)deviceExtension != '2slc');
3414
3415 //
3416 // Write length to SRB.
3417 //
3418
3419 Srb->Length = SCSI_REQUEST_BLOCK_SIZE;
3420
3421 //
3422 // Set SCSI bus address.
3423 //
3424
3425 Srb->PathId = deviceExtension->PathId;
3426 Srb->TargetId = deviceExtension->TargetId;
3427 Srb->Lun = deviceExtension->Lun;
3428
3429 Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
3430
3431 //
3432 // This is a violation of the SCSI spec but it is required for
3433 // some targets.
3434 //
3435
3436 Srb->Cdb[1] |= deviceExtension->Lun << 5;
3437
3438 //
3439 // Indicate auto request sense by specifying buffer and size.
3440 //
3441
3442 Srb->SenseInfoBuffer = deviceExtension->SenseData;
3443 Srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE;
3444 Srb->DataBuffer = BufferAddress;
3445
3446 if (BufferAddress != NULL) {
3447
3448 //
3449 // Build Mdl if necessary.
3450 //
3451
3452 if (Irp->MdlAddress == NULL) {
3453
3454 if (IoAllocateMdl(BufferAddress,
3455 BufferLength,
3456 FALSE,
3457 FALSE,
3458 Irp) == NULL) {
3459
3460 return(STATUS_INSUFFICIENT_RESOURCES);
3461 }
3462
3463 MmBuildMdlForNonPagedPool(Irp->MdlAddress);
3464
3465 } else {
3466
3467 //
3468 // Make sure the buffer requested matches the MDL.
3469 //
3470
3471 ASSERT(BufferAddress == MmGetMdlVirtualAddress(Irp->MdlAddress));
3472 }
3473
3474 //
3475 // Set read flag.
3476 //
3477
3478 Srb->SrbFlags = WriteToDevice ? SRB_FLAGS_DATA_OUT : SRB_FLAGS_DATA_IN;
3479
3480 } else {
3481
3482 //
3483 // Clear flags.
3484 //
3485
3486 Srb->SrbFlags = SRB_FLAGS_NO_DATA_TRANSFER;
3487 }
3488
3489 //
3490 // Disable synchronous transfer for these requests.
3491 //
3492
3493 Srb->SrbFlags |= SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
3494
3495 //
3496 // Set the transfer length.
3497 //
3498
3499 Srb->DataTransferLength = BufferLength;
3500
3501 //
3502 // Zero out status.
3503 //
3504
3505 Srb->ScsiStatus = Srb->SrbStatus = 0;
3506
3507 Srb->NextSrb = 0;
3508
3509 //
3510 // Save a few parameters in the current stack location.
3511 //
3512
3513 irpStack = IoGetCurrentIrpStackLocation(Irp);
3514
3515 //
3516 // Save retry count in current Irp stack.
3517 //
3518
3519 irpStack->Parameters.Others.Argument4 = (PVOID)MAXIMUM_RETRIES;
3520
3521 //
3522 // Set up IoCompletion routine address.
3523 //
3524
3525 IoSetCompletionRoutine(Irp, ScsiClassIoComplete, Srb, TRUE, TRUE, TRUE);
3526
3527 //
3528 // Get next stack location and
3529 // set major function code.
3530 //
3531
3532 irpStack = IoGetNextIrpStackLocation(Irp);
3533
3534 irpStack->MajorFunction = IRP_MJ_SCSI;
3535
3536 //
3537 // Save SRB address in next stack for port driver.
3538 //
3539
3540 irpStack->Parameters.Scsi.Srb = Srb;
3541
3542 //
3543 // Set up Irp Address.
3544 //
3545
3546 Srb->OriginalRequest = Irp;
3547
3548 //
3549 // Call the port driver to process the request.
3550 //
3551
3552 return(IoCallDriver(deviceExtension->PortDeviceObject, Irp));
3553
3554 }
3555
3556
3557 NTSTATUS
3558 NTAPI
3559 ScsiClassDeviceControlDispatch(
3560 PDEVICE_OBJECT DeviceObject,
3561 PIRP Irp
3562 )
3563
3564 /*++
3565
3566 Routine Description:
3567
3568 The routine is the common class driver device control dispatch entry point.
3569 This routine is invokes the device-specific drivers DeviceControl routine,
3570 (which may call the Class driver's common DeviceControl routine).
3571
3572 Arguments:
3573
3574 DeviceObject - Supplies a pointer to the device object for this request.
3575
3576 Irp - Supplies the Irp making the request.
3577
3578 Return Value:
3579
3580 Returns the status returned from the device-specific driver.
3581
3582 --*/
3583
3584 {
3585
3586 PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
3587
3588 ASSERT(*(PULONG)deviceExtension != '2slc');
3589
3590 //
3591 // Call the class specific driver DeviceControl routine.
3592 // If it doesn't handle it, it will call back into ScsiClassDeviceControl.
3593 //
3594
3595 ASSERT(deviceExtension->ClassDeviceControl);
3596
3597 return deviceExtension->ClassDeviceControl(DeviceObject,Irp);
3598 }
3599
3600
3601 NTSTATUS
3602 NTAPI
3603 ScsiClassDeviceControl(
3604 PDEVICE_OBJECT DeviceObject,
3605 PIRP Irp
3606 )
3607 /*++
3608
3609 Routine Description:
3610
3611 The routine is the common class driver device control dispatch function.
3612 This routine is called by a class driver when it get an unrecognized
3613 device control request. This routine will perform the correct action for
3614 common requests such as lock media. If the device request is unknown it
3615 passed down to the next level.
3616
3617 Arguments:
3618
3619 DeviceObject - Supplies a pointer to the device object for this request.
3620
3621 Irp - Supplies the Irp making the request.
3622
3623 Return Value:
3624
3625 Returns back a STATUS_PENDING or a completion status.
3626
3627 --*/
3628
3629 {
3630 PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
3631 PIO_STACK_LOCATION nextStack;
3632 PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
3633 PSCSI_REQUEST_BLOCK srb;
3634 PCDB cdb;
3635 NTSTATUS status;
3636 ULONG modifiedIoControlCode;
3637
3638 ASSERT(*(PULONG)deviceExtension != '2slc');
3639
3640 if (irpStack->Parameters.DeviceIoControl.IoControlCode ==
3641 IOCTL_STORAGE_RESET_DEVICE) {
3642
3643 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
3644 IoCompleteRequest(Irp, IO_NO_INCREMENT);
3645 status = STATUS_UNSUCCESSFUL;
3646 goto SetStatusAndReturn;
3647 }
3648
3649 //
3650 // If this is a pass through I/O control, set the minor function code
3651 // and device address and pass it to the port driver.
3652 //
3653
3654 if (irpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SCSI_PASS_THROUGH
3655 || irpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SCSI_PASS_THROUGH_DIRECT) {
3656
3657 PSCSI_PASS_THROUGH scsiPass;
3658
3659 nextStack = IoGetNextIrpStackLocation(Irp);
3660
3661 //
3662 // Validate the user buffer.
3663 //
3664
3665 if (irpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(SCSI_PASS_THROUGH)){
3666
3667 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
3668 IoCompleteRequest(Irp, IO_NO_INCREMENT);
3669 status = STATUS_INVALID_PARAMETER;
3670 goto SetStatusAndReturn;
3671 }
3672
3673 //
3674 // Force the SCSI address to the correct value.
3675 //
3676
3677 scsiPass = Irp->AssociatedIrp.SystemBuffer;
3678 scsiPass->PathId = deviceExtension->PathId;
3679 scsiPass->TargetId = deviceExtension->TargetId;
3680 scsiPass->Lun = deviceExtension->Lun;
3681
3682 //
3683 // NOTICE: The SCSI-II specification indicates that this field
3684 // should be zero; however, some target controllers ignore the logical
3685 // unit number in the IDENTIFY message and only look at the logical
3686 // unit number field in the CDB.
3687 //
3688
3689 scsiPass->Cdb[1] |= deviceExtension->Lun << 5;
3690
3691 nextStack->Parameters = irpStack->Parameters;
3692 nextStack->MajorFunction = irpStack->MajorFunction;
3693 nextStack->MinorFunction = IRP_MN_SCSI_CLASS;
3694
3695 status = IoCallDriver(deviceExtension->PortDeviceObject, Irp);
3696 goto SetStatusAndReturn;
3697 }
3698
3699 if (irpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SCSI_GET_ADDRESS) {
3700
3701 PSCSI_ADDRESS scsiAddress = Irp->AssociatedIrp.SystemBuffer;
3702
3703 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
3704 sizeof(SCSI_ADDRESS)) {
3705
3706 //
3707 // Indicate unsuccessful status and no data transferred.
3708 //
3709
3710 Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
3711 Irp->IoStatus.Information = 0;
3712 IoCompleteRequest(Irp, IO_NO_INCREMENT);
3713 status = STATUS_BUFFER_TOO_SMALL;
3714 goto SetStatusAndReturn;
3715
3716 }
3717
3718 scsiAddress->Length = sizeof(SCSI_ADDRESS);
3719 scsiAddress->PortNumber = deviceExtension->PortNumber;
3720 scsiAddress->PathId = deviceExtension->PathId;
3721 scsiAddress->TargetId = deviceExtension->TargetId;
3722 scsiAddress->Lun = deviceExtension->Lun;
3723 Irp->IoStatus.Information = sizeof(SCSI_ADDRESS);
3724 Irp->IoStatus.Status = STATUS_SUCCESS;
3725 IoCompleteRequest(Irp, IO_NO_INCREMENT);
3726 status = STATUS_SUCCESS;
3727 goto SetStatusAndReturn;
3728 }
3729
3730 if (irpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME) {
3731
3732 UNIMPLEMENTED;
3733 Irp->IoStatus.Information = 0;
3734 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
3735 IoCompleteRequest(Irp, IO_NO_INCREMENT);
3736 status = STATUS_NOT_IMPLEMENTED;
3737 goto SetStatusAndReturn;
3738 }
3739
3740 if (irpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_MOUNTDEV_QUERY_UNIQUE_ID) {
3741
3742 //
3743 // FIXME
3744 // This is a HACK. We don't have unique ID.
3745 // We'll just return device name as unique ID.
3746 // It's unique but may not survive to a reboot,
3747 // which is not matching the requirements for
3748 // a MountMgr unique ID.
3749 //
3750
3751 PMOUNTDEV_UNIQUE_ID uniqueId = Irp->AssociatedIrp.SystemBuffer;
3752
3753 //
3754 // Check output buffer is big enough.
3755 //
3756
3757 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(MOUNTDEV_UNIQUE_ID)) {
3758
3759 Irp->IoStatus.Information = 0;
3760 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
3761 IoCompleteRequest(Irp, IO_NO_INCREMENT);
3762 status = STATUS_INVALID_PARAMETER;
3763 goto SetStatusAndReturn;
3764 }
3765
3766 //
3767 // Set size we'll return so that caller can allocate big enough buffer.
3768 //
3769
3770 RtlZeroMemory(uniqueId, sizeof(MOUNTDEV_UNIQUE_ID));
3771 uniqueId->UniqueIdLength = deviceExtension->DeviceName.Length;
3772
3773 //
3774 // Check buffer is big enough to contain device name.
3775 //
3776
3777 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < FIELD_OFFSET(MOUNTDEV_UNIQUE_ID, UniqueId) + uniqueId->UniqueIdLength) {
3778
3779 Irp->IoStatus.Information = sizeof(MOUNTDEV_UNIQUE_ID);
3780 Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
3781 IoCompleteRequest(Irp, IO_NO_INCREMENT);
3782 status = STATUS_BUFFER_OVERFLOW;
3783 goto SetStatusAndReturn;
3784 }
3785
3786 //
3787 // Copy device name.
3788 //
3789
3790 RtlCopyMemory(uniqueId->UniqueId, deviceExtension->DeviceName.Buffer,
3791 uniqueId->UniqueIdLength);
3792 status = STATUS_SUCCESS;
3793
3794 //
3795 // And return to the caller.
3796 //
3797
3798 Irp->IoStatus.Status = STATUS_SUCCESS;
3799 Irp->IoStatus.Information = FIELD_OFFSET(MOUNTDEV_UNIQUE_ID, UniqueId) + uniqueId->UniqueIdLength;
3800 IoCompleteRequest(Irp, IO_NO_INCREMENT);
3801 goto SetStatusAndReturn;
3802 }
3803
3804 if (irpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_MOUNTDEV_QUERY_DEVICE_NAME) {
3805
3806 PMOUNTDEV_NAME name = Irp->AssociatedIrp.SystemBuffer;
3807
3808 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(MOUNTDEV_NAME)) {
3809
3810 Irp->IoStatus.Information = 0;
3811 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
3812 IoCompleteRequest(Irp, IO_NO_INCREMENT);
3813 status = STATUS_INVALID_PARAMETER;
3814 goto SetStatusAndReturn;
3815 }
3816
3817 RtlZeroMemory(name, sizeof(MOUNTDEV_NAME));
3818 name->NameLength = deviceExtension->DeviceName.Length;
3819
3820 if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < FIELD_OFFSET(MOUNTDEV_NAME, Name) + name->NameLength) {
3821
3822 Irp->IoStatus.Information = sizeof(MOUNTDEV_NAME);
3823 Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
3824 IoCompleteRequest(Irp, IO_NO_INCREMENT);
3825 status = STATUS_BUFFER_OVERFLOW;
3826 goto SetStatusAndReturn;
3827 }
3828
3829 RtlCopyMemory(name->Name, deviceExtension->DeviceName.Buffer,
3830 name->NameLength);
3831 status = STATUS_SUCCESS;
3832 Irp->IoStatus.Status = STATUS_SUCCESS;
3833 Irp->IoStatus.Information = FIELD_OFFSET(MOUNTDEV_NAME, Name) + name->NameLength;
3834 IoCompleteRequest(Irp, IO_NO_INCREMENT);
3835 goto SetStatusAndReturn;
3836 }
3837
3838 srb = ExAllocatePool(NonPagedPool, SCSI_REQUEST_BLOCK_SIZE);
3839
3840 if (srb == NULL) {
3841
3842 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
3843 IoCompleteRequest(Irp, IO_NO_INCREMENT);
3844 status = STATUS_INSUFFICIENT_RESOURCES;
3845 goto SetStatusAndReturn;
3846 }
3847
3848 //
3849 // Write zeros to Srb.
3850 //
3851
3852 RtlZeroMemory(srb, SCSI_REQUEST_BLOCK_SIZE);
3853
3854 cdb = (PCDB)srb->Cdb;
3855
3856 //
3857 // Change the device type to disk for the switch statement.
3858 //
3859
3860 modifiedIoControlCode = (irpStack->Parameters.DeviceIoControl.IoControlCode
3861 & ~0xffff0000) | (IOCTL_DISK_BASE << 16);
3862
3863 switch (modifiedIoControlCode) {
3864
3865 case IOCTL_DISK_CHECK_VERIFY: {
3866
3867 PIRP irp2 = NULL;
3868 PIO_STACK_LOCATION newStack;
3869
3870 DebugPrint((1,"ScsiDeviceIoControl: Check verify\n"));
3871
3872 //
3873 // If a buffer for a media change count was provided, make sure it's
3874 // big enough to hold the result
3875 //
3876
3877 if(irpStack->Parameters.DeviceIoControl.OutputBufferLength) {
3878
3879 //
3880 // If the buffer is too small to hold the media change count
3881 // then return an error to the caller
3882 //
3883
3884 if(irpStack->Parameters.DeviceIoControl.OutputBufferLength <
3885 sizeof(ULONG)) {
3886
3887 DebugPrint((3,"ScsiDeviceIoControl: media count "
3888 "buffer too small\n"));
3889
3890 Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
3891 Irp->IoStatus.Information = 0;
3892 ExFreePool(srb);
3893 IoCompleteRequest(Irp, IO_NO_INCREMENT);
3894 status = STATUS_BUFFER_TOO_SMALL;
3895 goto SetStatusAndReturn;
3896
3897 }
3898
3899 //
3900 // The caller has provided a valid buffer. Allocate an additional
3901 // irp and stick the CheckVerify completion routine on it. We will
3902 // then send this down to the port driver instead of the irp the
3903 // caller sent in
3904 //
3905
3906 DebugPrint((2,"ScsiDeviceIoControl: Check verify wants "
3907 "media count\n"));
3908
3909 //
3910 // Allocate a new irp to send the TestUnitReady to the port driver
3911 //
3912
3913 irp2 = IoAllocateIrp((CCHAR) (DeviceObject->StackSize + 3), FALSE);
3914
3915 if(irp2 == NULL) {
3916 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
3917 Irp->IoStatus.Information = 0;
3918 ExFreePool(srb);
3919 IoCompleteRequest(Irp, IO_NO_INCREMENT);
3920 status = STATUS_INSUFFICIENT_RESOURCES;
3921 goto SetStatusAndReturn;
3922 }
3923
3924 irp2->Tail.Overlay.Thread = Irp->Tail.Overlay.Thread;
3925 IoSetNextIrpStackLocation(irp2);
3926
3927 //
3928 // Set the top stack location and shove the master Irp into the
3929 // top location
3930 //
3931
3932 newStack = IoGetCurrentIrpStackLocation(irp2);
3933 newStack->Parameters.Others.Argument1 = Irp;
3934 newStack->DeviceObject = DeviceObject;
3935
3936 //
3937 // Stick the check verify completion routine onto the stack
3938 // and prepare the irp for the port driver
3939 //
3940
3941 IoSetCompletionRoutine(irp2,
3942 ScsiClassCheckVerifyComplete,
3943 NULL,
3944 TRUE,
3945 TRUE,
3946 TRUE);
3947
3948 IoSetNextIrpStackLocation(irp2);
3949 newStack = IoGetCurrentIrpStackLocation(irp2);
3950 newStack->DeviceObject = DeviceObject;
3951
3952 //
3953 // Mark the master irp as pending - whether the lower level
3954 // driver completes it immediately or not this should allow it
3955 // to go all the way back up.
3956 //
3957
3958 IoMarkIrpPending(Irp);
3959
3960 Irp = irp2;
3961
3962 }
3963
3964 //
3965 // Test Unit Ready
3966 //
3967
3968 srb->CdbLength = 6;
3969 cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY;
3970
3971 //
3972 // Set timeout value.
3973 //
3974
3975 srb->TimeOutValue = deviceExtension->TimeOutValue;
3976
3977 //
3978 // Since this routine will always hand the request to the
3979 // port driver if there isn't a data transfer to be done
3980 // we don't have to worry about completing the request here
3981 // on an error
3982 //
3983
3984 status = ScsiClassSendSrbAsynchronous(DeviceObject,
3985 srb,
3986 Irp,
3987 NULL,
3988 0,
3989 FALSE);
3990
3991 break;
3992 }
3993
3994 case IOCTL_DISK_MEDIA_REMOVAL: {
3995
3996 PPREVENT_MEDIA_REMOVAL MediaRemoval = Irp->AssociatedIrp.SystemBuffer;
3997
3998 //
3999 // Prevent/Allow media removal.
4000 //
4001
4002 DebugPrint((3,"DiskIoControl: Prevent/Allow media removal\n"));
4003
4004 if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
4005 sizeof(PREVENT_MEDIA_REMOVAL)) {
4006
4007 //
4008 // Indicate unsuccessful status and no data transferred.
4009 //
4010
4011 Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
4012 Irp->IoStatus.Information = 0;
4013 ExFreePool(srb);
4014 IoCompleteRequest(Irp, IO_NO_INCREMENT);
4015 status = STATUS_BUFFER_TOO_SMALL;
4016 goto SetStatusAndReturn;
4017 }
4018
4019 //
4020 // Get physical device extension. This is where the
4021 // lock count is stored.
4022 //
4023
4024 deviceExtension = deviceExtension->PhysicalDevice->DeviceExtension;
4025
4026 //
4027 // If command succeeded then increment or decrement lock counter.
4028 //
4029
4030 if (MediaRemoval->PreventMediaRemoval) {
4031
4032 //
4033 // This is a lock command. Reissue the command in case bus or device
4034 // was reset and lock cleared.
4035 //
4036
4037 InterlockedIncrement(&deviceExtension->LockCount);
4038
4039 DebugPrint((1,
4040 "ScsiClassDeviceControl: Lock media, lock count %x on disk %x\n",
4041 deviceExtension->LockCount,
4042 deviceExtension->DeviceNumber));
4043
4044 } else {
4045
4046 //
4047 // This is an unlock command.
4048 //
4049
4050 if (!deviceExtension->LockCount ||
4051 (InterlockedDecrement(&deviceExtension->LockCount) != 0)) {
4052
4053 DebugPrint((1,
4054 "ScsiClassDeviceControl: Unlock media, lock count %x on disk %x\n",
4055 deviceExtension->LockCount,
4056 deviceExtension->DeviceNumber));
4057
4058 //
4059 // Don't unlock because someone still wants it locked.
4060 //
4061
4062 Irp->IoStatus.Status = STATUS_SUCCESS;
4063 ExFreePool(srb);
4064 IoCompleteRequest(Irp, IO_NO_INCREMENT);
4065 status = STATUS_SUCCESS;
4066 goto SetStatusAndReturn;
4067 }
4068
4069 DebugPrint((1,
4070 "ScsiClassDeviceControl: Unlock media, lock count %x on disk %x\n",
4071 deviceExtension->LockCount,
4072 deviceExtension->DeviceNumber));
4073 }
4074
4075 srb->CdbLength = 6;
4076
4077 cdb->MEDIA_REMOVAL.OperationCode = SCSIOP_MEDIUM_REMOVAL;
4078
4079 //
4080 // TRUE - prevent media removal.
4081 // FALSE - allow media removal.
4082 //
4083
4084 cdb->MEDIA_REMOVAL.Prevent = MediaRemoval->PreventMediaRemoval;
4085
4086 //
4087 // Set timeout value.
4088 //
4089
4090 srb->TimeOutValue = deviceExtension->TimeOutValue;
4091 status = ScsiClassSendSrbAsynchronous(DeviceObject,
4092 srb,
4093 Irp,
4094 NULL,
4095 0,
4096 FALSE);
4097
4098 //
4099 // Some devices will not support lock/unlock.
4100 // Pretend that it worked.
4101 //
4102
4103 break;
4104 }
4105
4106 case IOCTL_DISK_RESERVE: {
4107
4108 //
4109 // Reserve logical unit.
4110 //
4111
4112 srb->CdbLength = 6;
4113
4114 cdb->CDB6GENERIC.OperationCode = SCSIOP_RESERVE_UNIT;
4115
4116 //
4117 // Set timeout value.
4118 //
4119
4120 srb->TimeOutValue = deviceExtension->TimeOutValue;
4121
4122 status = ScsiClassSendSrbAsynchronous(DeviceObject,
4123 srb,
4124 Irp,
4125 NULL,
4126 0,
4127 FALSE);
4128
4129 break;
4130 }
4131
4132 case IOCTL_DISK_RELEASE: {
4133
4134 //
4135 // Release logical unit.
4136 //
4137
4138 srb->CdbLength = 6;
4139
4140 cdb->CDB6GENERIC.OperationCode = SCSIOP_RELEASE_UNIT;
4141
4142 //
4143 // Set timeout value.
4144 //
4145
4146 srb->TimeOutValue = deviceExtension->TimeOutValue;
4147
4148 status = ScsiClassSendSrbAsynchronous(DeviceObject,
4149 srb,
4150 Irp,
4151 NULL,
4152 0,
4153 FALSE);
4154
4155 break;
4156 }
4157
4158 case IOCTL_DISK_EJECT_MEDIA: {
4159
4160 //
4161 // Eject media.
4162 //
4163
4164 srb->CdbLength = 6;
4165
4166 cdb->START_STOP.OperationCode = SCSIOP_START_STOP_UNIT;
4167 cdb->START_STOP.LoadEject = 1;
4168 cdb->START_STOP.Start = 0;
4169
4170 //
4171 // Set timeout value.
4172 //
4173
4174 srb->TimeOutValue = deviceExtension->TimeOutValue;
4175 status = ScsiClassSendSrbAsynchronous(DeviceObject,
4176 srb,
4177 Irp,
4178 NULL,
4179 0,
4180 FALSE);
4181 break;
4182 }
4183
4184 case IOCTL_DISK_LOAD_MEDIA: {
4185
4186 //
4187 // Load media.
4188 //
4189
4190 DebugPrint((3,"CdRomDeviceControl: Load media\n"));
4191
4192 srb->CdbLength = 6;
4193
4194 cdb->START_STOP.OperationCode = SCSIOP_START_STOP_UNIT;
4195 cdb->START_STOP.LoadEject = 1;
4196 cdb->START_STOP.Start = 1;
4197
4198 //
4199 // Set timeout value.
4200 //
4201
4202 srb->TimeOutValue = deviceExtension->TimeOutValue;
4203 status = ScsiClassSendSrbAsynchronous(DeviceObject,
4204 srb,
4205 Irp,
4206 NULL,
4207 0,
4208 FALSE);
4209
4210 break;
4211 }
4212
4213 case IOCTL_DISK_FIND_NEW_DEVICES: {
4214
4215 //
4216 // Search for devices that have been powered on since the last
4217 // device search or system initialization.
4218 //
4219
4220 DebugPrint((3,"CdRomDeviceControl: Find devices\n"));
4221 status = DriverEntry(DeviceObject->DriverObject,
4222 NULL);
4223
4224 Irp->IoStatus.Status = status;
4225 ExFreePool(srb);
4226 IoCompleteRequest(Irp, IO_NO_INCREMENT);
4227
4228 break;
4229 }
4230
4231 default: {
4232
4233 DebugPrint((3,"ScsiIoDeviceControl: Unsupported device IOCTL\n"));
4234
4235 //
4236 // Pass the device control to the next driver.
4237 //
4238
4239 ExFreePool(srb);
4240
4241 //
4242 // Copy the Irp stack parameters to the next stack location.
4243 //
4244
4245 nextStack = IoGetNextIrpStackLocation(Irp);
4246 nextStack->Parameters = irpStack->Parameters;
4247 nextStack->MajorFunction = irpStack->MajorFunction;
4248 nextStack->MinorFunction = irpStack->MinorFunction;
4249
4250 status = IoCallDriver(deviceExtension->PortDeviceObject, Irp);
4251 break;
4252 }
4253
4254 } // end switch( ...
4255
4256 SetStatusAndReturn:
4257
4258 return status;
4259 }
4260
4261
4262 NTSTATUS
4263 NTAPI
4264 ScsiClassShutdownFlush(
4265 IN PDEVICE_OBJECT DeviceObject,
4266 IN PIRP Irp
4267 )
4268
4269 /*++
4270
4271 Routine Description:
4272
4273 This routine is called for a shutdown and flush IRPs. These are sent by the
4274 system before it actually shuts down or when the file system does a flush.
4275 If it exists, the device-specific driver's routine will be invoked. If there
4276 wasn't one specified, the Irp will be completed with an Invalid device request.
4277
4278 Arguments:
4279
4280 DriverObject - Pointer to device object to being shutdown by system.
4281
4282 Irp - IRP involved.
4283
4284 Return Value:
4285
4286 NT Status
4287
4288 --*/
4289
4290 {
4291 PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
4292
4293 ASSERT(*(PULONG)deviceExtension != '2slc');
4294
4295 if (deviceExtension->ClassShutdownFlush) {
4296
4297 //
4298 // Call the device-specific driver's routine.
4299 //
4300
4301 return deviceExtension->ClassShutdownFlush(DeviceObject, Irp);
4302 }
4303
4304 //
4305 // Device-specific driver doesn't support this.
4306 //
4307
4308 Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
4309 IoCompleteRequest(Irp, IO_NO_INCREMENT);
4310
4311 return STATUS_INVALID_DEVICE_REQUEST;
4312 }
4313
4314
4315 ULONG
4316 NTAPI
4317 ScsiClassFindUnclaimedDevices(
4318 IN PCLASS_INIT_DATA InitializationData,
4319 IN PSCSI_ADAPTER_BUS_INFO AdapterInformation
4320 )
4321
4322 {
4323 ULONG scsiBus,deviceCount = 0;
4324 PCHAR buffer = (PCHAR)AdapterInformation;
4325 PSCSI_INQUIRY_DATA lunInfo;
4326 PINQUIRYDATA inquiryData;
4327
4328 for (scsiBus=0; scsiBus < (ULONG)AdapterInformation->NumberOfBuses; scsiBus++) {
4329
4330 //
4331 // Get the SCSI bus scan data for this bus.
4332 //
4333
4334 lunInfo = (PVOID) (buffer + AdapterInformation->BusData[scsiBus].InquiryDataOffset);
4335
4336 //
4337 // Search list for unclaimed disk devices.
4338 //
4339
4340 while (AdapterInformation->BusData[scsiBus].InquiryDataOffset) {
4341
4342 inquiryData = (PVOID)lunInfo->InquiryData;
4343
4344 ASSERT(InitializationData->ClassFindDeviceCallBack);
4345
4346 if ((InitializationData->ClassFindDeviceCallBack(inquiryData)) && (!lunInfo->DeviceClaimed)) {
4347
4348 deviceCount++;
4349 }
4350
4351 if (lunInfo->NextInquiryDataOffset == 0) {
4352 break;
4353 }
4354
4355 lunInfo = (PVOID) (buffer + lunInfo->NextInquiryDataOffset);
4356 }
4357 }
4358 return deviceCount;
4359 }
4360
4361
4362
4363 NTSTATUS
4364 NTAPI
4365 ScsiClassCreateDeviceObject(
4366 IN PDRIVER_OBJECT DriverObject,
4367 IN PCCHAR ObjectNameBuffer,
4368 IN OPTIONAL PDEVICE_OBJECT PhysicalDeviceObject,
4369 IN OUT PDEVICE_OBJECT *DeviceObject,
4370 IN PCLASS_INIT_DATA InitializationData
4371 )
4372
4373 /*++
4374
4375 Routine Description:
4376
4377 This routine creates an object for the physical device specified and
4378 sets up the deviceExtension's function pointers for each entry point
4379 in the device-specific driver.
4380
4381 Arguments:
4382
4383 DriverObject - Pointer to driver object created by system.
4384
4385 ObjectNameBuffer - Dir. name of the object to create.
4386
4387 PhysicalDeviceObject - Pointer to the physical (class) device object for
4388 this logical unit or NULL if this is it.
4389
4390 DeviceObject - Pointer to the device object pointer we will return.
4391
4392 InitializationData - Pointer to the init data created by the device-specific driver.
4393
4394 Return Value:
4395
4396 NTSTATUS
4397
4398 --*/
4399
4400 {
4401 STRING ntNameString;
4402 UNICODE_STRING ntUnicodeString;
4403 NTSTATUS status;
4404 PDEVICE_OBJECT deviceObject = NULL;
4405
4406 *DeviceObject = NULL;
4407
4408 DebugPrint((2,
4409 "ScsiClassCreateDeviceObject: Create device object %s\n",
4410 ObjectNameBuffer));
4411
4412 RtlInitString(&ntNameString,
4413 ObjectNameBuffer);
4414
4415 status = RtlAnsiStringToUnicodeString(&ntUnicodeString,
4416 &ntNameString,
4417 TRUE);
4418
4419 if (!NT_SUCCESS(status)) {
4420
4421 DebugPrint((1,
4422 "CreateDiskDeviceObjects: Cannot convert string %s\n",
4423 ObjectNameBuffer));
4424
4425 ntUnicodeString.Buffer = NULL;
4426 return status;
4427 }
4428
4429 status = IoCreateDevice(DriverObject,
4430 InitializationData->DeviceExtensionSize,
4431 &ntUnicodeString,
4432 InitializationData->DeviceType,
4433 InitializationData->DeviceCharacteristics,
4434 FALSE,
4435 &deviceObject);
4436
4437
4438 if (!NT_SUCCESS(status)) {
4439
4440 DebugPrint((1,
4441 "CreateDiskDeviceObjects: Can not create device object %s\n",
4442 ObjectNameBuffer));
4443
4444 } else {
4445
4446 PDEVICE_EXTENSION deviceExtension = deviceObject->DeviceExtension;
4447
4448 ASSERT(*(PULONG)deviceExtension != '2slc');
4449
4450 //
4451 // Fill in entry points
4452 //
4453
4454 deviceExtension->ClassError = InitializationData->ClassError;
4455 deviceExtension->ClassReadWriteVerification = InitializationData->ClassReadWriteVerification;
4456 deviceExtension->ClassFindDevices = InitializationData->ClassFindDevices;
4457 deviceExtension->ClassDeviceControl = InitializationData->ClassDeviceControl;
4458 deviceExtension->ClassShutdownFlush = InitializationData->ClassShutdownFlush;
4459 deviceExtension->ClassCreateClose = InitializationData->ClassCreateClose;
4460 deviceExtension->ClassStartIo = InitializationData->ClassStartIo;
4461
4462 deviceExtension->MediaChangeCount = 0;
4463
4464 //
4465 // If a pointer to the physical device object was passed in then use
4466 // that. If the value was NULL, then this is the physical device so
4467 // use the pointer to the device we just created.
4468 //
4469
4470 if(ARGUMENT_PRESENT(PhysicalDeviceObject)) {
4471 deviceExtension->PhysicalDevice = PhysicalDeviceObject;
4472 } else {
4473 deviceExtension->PhysicalDevice = deviceObject;
4474 }
4475
4476 deviceExtension->DeviceName = ntUnicodeString;
4477 }
4478
4479 deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
4480
4481 *DeviceObject = deviceObject;
4482
4483 return status;
4484 }
4485
4486
4487 NTSTATUS
4488 NTAPI
4489 ScsiClassClaimDevice(
4490 IN PDEVICE_OBJECT PortDeviceObject,
4491 IN PSCSI_INQUIRY_DATA LunInfo,
4492 IN BOOLEAN Release,
4493 OUT PDEVICE_OBJECT *NewPortDeviceObject OPTIONAL
4494 )
4495 /*++
4496
4497 Routine Description:
4498
4499 This function claims a device in the port driver. The port driver object
4500 is updated with the correct driver object if the device is successfully
4501 claimed.
4502
4503 Arguments:
4504
4505 PortDeviceObject - Supplies the base port device object.
4506
4507 LunInfo - Supplies the logical unit inforamtion of the device to be claimed.
4508
4509 Release - Indicates the logical unit should be released rather than claimed.
4510
4511 NewPortDeviceObject - Returns the updated port device object to be used
4512 for all future accesses.
4513
4514 Return Value:
4515
4516 Returns a status indicating success or failure of the operation.
4517
4518 --*/
4519
4520 {
4521 IO_STATUS_BLOCK ioStatus;
4522 PIRP irp;
4523 PIO_STACK_LOCATION irpStack;
4524 KEVENT event;
4525 NTSTATUS status;
4526 SCSI_REQUEST_BLOCK srb;
4527
4528 PAGED_CODE();
4529
4530 if (NewPortDeviceObject != NULL) {
4531 *NewPortDeviceObject = NULL;
4532 }
4533
4534 //
4535 // Clear the SRB fields.
4536 //
4537
4538 RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK));
4539
4540 //
4541 // Write length to SRB.
4542 //
4543
4544 srb.Length = SCSI_REQUEST_BLOCK_SIZE;
4545
4546 //
4547 // Set SCSI bus address.
4548 //
4549
4550 srb.PathId = LunInfo->PathId;
4551 srb.TargetId = LunInfo->TargetId;
4552 srb.Lun = LunInfo->Lun;
4553
4554 srb.Function = Release ? SRB_FUNCTION_RELEASE_DEVICE :
4555 SRB_FUNCTION_CLAIM_DEVICE;
4556
4557 //
4558 // Set the event object to the unsignaled state.
4559 // It will be used to signal request completion.
4560 //
4561
4562 KeInitializeEvent(&event, NotificationEvent, FALSE);
4563
4564 //
4565 // Build synchronous request with no transfer.
4566 //
4567
4568 irp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_EXECUTE_NONE,
4569 PortDeviceObject,
4570 NULL,
4571 0,
4572 NULL,
4573 0,
4574 TRUE,
4575 &event,
4576 &ioStatus);
4577
4578 if (irp == NULL) {
4579
4580 DebugPrint((1, "ScsiClassClaimDevice: Can't allocate Irp\n"));
4581 return STATUS_INSUFFICIENT_RESOURCES;
4582 }
4583
4584 irpStack = IoGetNextIrpStackLocation(irp);
4585
4586 //
4587 // Save SRB address in next stack for port driver.
4588 //
4589
4590 irpStack->Parameters.Scsi.Srb = &srb;
4591
4592 //
4593 // Set up IRP Address.
4594 //
4595
4596 srb.OriginalRequest = irp;
4597
4598 //
4599 // Call the port driver with the request and wait for it to complete.
4600 //
4601
4602 status = IoCallDriver(PortDeviceObject, irp);
4603 if (status == STATUS_PENDING) {
4604
4605 KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, NULL);
4606 status = ioStatus.Status;
4607 }
4608
4609 //
4610 // If this is a release request, then just decrement the reference count
4611 // and return. The status does not matter.
4612 //
4613
4614 if (Release) {
4615
4616 //ObDereferenceObject(PortDeviceObject);
4617 return STATUS_SUCCESS;
4618 }
4619
4620 if (!NT_SUCCESS(status)) {
4621 return status;
4622 }
4623
4624 ASSERT(srb.DataBuffer != NULL);
4625
4626 //
4627 // Reference the new port driver object so that it will not go away while
4628 // it is being used.
4629 //
4630
4631 status = ObReferenceObjectByPointer(srb.DataBuffer,
4632 0,
4633 NULL,
4634 KernelMode );
4635
4636 if (!NT_SUCCESS(status)) {
4637
4638 return status;
4639 }
4640 ObDereferenceObject(srb.DataBuffer);
4641
4642 //
4643 // Return the new port device object pointer.
4644 //
4645
4646 if (NewPortDeviceObject != NULL) {
4647 *NewPortDeviceObject = srb.DataBuffer;
4648 }
4649
4650 return status;
4651 }
4652
4653
4654 NTSTATUS
4655 NTAPI
4656 ScsiClassInternalIoControl (
4657 IN PDEVICE_OBJECT DeviceObject,
4658 IN PIRP Irp
4659 )
4660
4661 /*++
4662
4663 Routine Description:
4664
4665 This routine passes internal device controls to the port driver.
4666 Internal device controls are used by higher level class drivers to
4667 send scsi requests to a device that are not normally sent by a generic
4668 class driver.
4669
4670 The path ID, target ID and logical unit ID are set in the srb so the
4671 higher level driver does not have to figure out what values are actually
4672 used.
4673
4674 Arguments:
4675
4676 DeviceObject - Supplies a pointer to the device object for this request.
4677
4678 Irp - Supplies the Irp making the request.
4679
4680 Return Value:
4681
4682 Returns back a STATUS_PENDING or a completion status.
4683
4684 --*/
4685 {
4686 PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
4687 PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
4688 PSCSI_REQUEST_BLOCK srb;
4689
4690 ASSERT(*(PULONG)deviceExtension != '2slc');
4691
4692 //
4693 // Get a pointer to the SRB.
4694 //
4695
4696 srb = irpStack->Parameters.Scsi.Srb;
4697
4698 //
4699 // Set SCSI bus address.
4700 //
4701
4702 srb->PathId = deviceExtension->PathId;
4703 srb->TargetId = deviceExtension->TargetId;
4704 srb->Lun = deviceExtension->Lun;
4705
4706 //
4707 // NOTICE: The SCSI-II specification indicates that this field should be
4708 // zero; however, some target controllers ignore the logical unit number
4709 // in the IDENTIFY message and only look at the logical unit number field
4710 // in the CDB.
4711 //
4712
4713 srb->Cdb[1] |= deviceExtension->Lun << 5;
4714
4715 //
4716 // Set the parameters in the next stack location.
4717 //
4718
4719 irpStack = IoGetNextIrpStackLocation(Irp);
4720
4721 irpStack->Parameters.Scsi.Srb = srb;
4722 irpStack->MajorFunction = IRP_MJ_SCSI;
4723 irpStack->MinorFunction = IRP_MN_SCSI_CLASS;
4724
4725 IoSetCompletionRoutine(Irp, ClassIoCompletion, NULL, TRUE, TRUE, TRUE);
4726 return IoCallDriver(deviceExtension->PortDeviceObject, Irp);
4727 }
4728
4729 NTSTATUS
4730 NTAPI
4731 ClassIoCompletion(
4732 IN PDEVICE_OBJECT DeviceObject,
4733 IN PIRP Irp,
4734 IN PVOID Context
4735 )
4736
4737 /*++
4738
4739 Routine Description:
4740
4741 This routine is called when an internal device control I/O request
4742 has completed. It marks the IRP pending if necessary and returns the
4743 status of the request.
4744
4745 Arguments:
4746
4747 DeviceObject - Target device object.
4748
4749 Irp - Completed request.
4750
4751 Context - not used.
4752
4753 Return Value:
4754
4755 Returns the status of the completed request.
4756
4757 --*/
4758
4759 {
4760 UNREFERENCED_PARAMETER(Context);
4761 UNREFERENCED_PARAMETER(DeviceObject);
4762
4763 //
4764 // If pending is returned for this Irp then mark current stack
4765 // as pending
4766 //
4767
4768 if (Irp->PendingReturned) {
4769
4770 IoMarkIrpPending( Irp );
4771 }
4772
4773 return Irp->IoStatus.Status;
4774 }
4775
4776
4777 VOID
4778 NTAPI
4779 ScsiClassInitializeSrbLookasideList(
4780 IN PDEVICE_EXTENSION DeviceExtension,
4781 IN ULONG NumberElements
4782 )
4783
4784 /*++
4785
4786 Routine Description:
4787
4788 This routine sets up a lookaside listhead for srbs.
4789
4790 Arguments:
4791
4792 DeviceExtension - Pointer to the deviceExtension containing the listhead.
4793
4794 NumberElements - Supplies the maximum depth of the lookaside list.
4795
4796
4797 Return Value:
4798
4799 None
4800
4801 --*/
4802
4803 {
4804 ExInitializeNPagedLookasideList(&DeviceExtension->SrbLookasideListHead,
4805 NULL,
4806 NULL,
4807 NonPagedPoolMustSucceed,
4808 SCSI_REQUEST_BLOCK_SIZE,
4809 'HscS',
4810 (USHORT)NumberElements);
4811
4812 }
4813
4814
4815 ULONG
4816 NTAPI
4817 ScsiClassQueryTimeOutRegistryValue(
4818 IN PUNICODE_STRING RegistryPath
4819 )
4820
4821 /*++
4822
4823 Routine Description:
4824
4825 This routine determines whether a reg key for a user-specified timeout value exists.
4826
4827 Arguments:
4828
4829 RegistryPath - Pointer to the hardware reg. entry describing the key.
4830
4831 Return Value:
4832
4833 New default timeout for a class of devices.
4834
4835 --*/
4836
4837 {
4838 //
4839 // Find the appropriate reg. key
4840 //
4841
4842 PRTL_QUERY_REGISTRY_TABLE parameters = NULL;
4843 PWSTR path;
4844 NTSTATUS status;
4845 LONG timeOut = 0;
4846 ULONG zero = 0;
4847 ULONG size;
4848
4849 if (!RegistryPath) {
4850 return 0;
4851 }
4852
4853 parameters = ExAllocatePool(NonPagedPool,
4854 sizeof(RTL_QUERY_REGISTRY_TABLE)*2);
4855
4856 if (!parameters) {
4857 return 0;
4858 }
4859
4860 size = RegistryPath->MaximumLength + sizeof(WCHAR);
4861 path = ExAllocatePool(NonPagedPool, size);
4862
4863 if (!path) {
4864 ExFreePool(parameters);
4865 return 0;
4866 }
4867
4868 RtlZeroMemory(path,size);
4869 RtlCopyMemory(path, RegistryPath->Buffer, size - sizeof(WCHAR));
4870
4871
4872 //
4873 // Check for the Timeout value.
4874 //
4875
4876 RtlZeroMemory(parameters,
4877 (sizeof(RTL_QUERY_REGISTRY_TABLE)*2));
4878
4879 parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
4880 parameters[0].Name = L"TimeOutValue";
4881 parameters[0].EntryContext = &timeOut;
4882 parameters[0].DefaultType = REG_DWORD;
4883 parameters[0].DefaultData = &zero;
4884 parameters[0].DefaultLength = sizeof(ULONG);
4885
4886 status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
4887 path,
4888 parameters,
4889 NULL,
4890 NULL);
4891
4892 if (!(NT_SUCCESS(status))) {
4893 timeOut = 0;
4894 }
4895
4896 ExFreePool(parameters);
4897 ExFreePool(path);
4898
4899 DebugPrint((2,
4900 "ScsiClassQueryTimeOutRegistryValue: Timeout value %d\n",
4901 timeOut));
4902
4903
4904 return timeOut;
4905
4906 }
4907
4908 NTSTATUS
4909 NTAPI
4910 ScsiClassCheckVerifyComplete(
4911 IN PDEVICE_OBJECT DeviceObject,
4912 IN PIRP Irp,
4913 IN PVOID Context
4914 )
4915
4916 /*++
4917
4918 Routine Description:
4919
4920 This routine executes when the port driver has completed a check verify
4921 ioctl. It will set the status of the master Irp, copy the media change
4922 count and complete the request.
4923
4924 Arguments:
4925
4926 DeviceObject - Supplies the device object which represents the logical
4927 unit.
4928
4929 Irp - Supplies the Irp which has completed.
4930
4931 Context - NULL
4932
4933 Return Value:
4934
4935 NT status
4936
4937 --*/
4938
4939 {
4940 PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
4941 PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
4942 PDEVICE_EXTENSION physicalExtension =
4943 deviceExtension->PhysicalDevice->DeviceExtension;
4944 PIRP originalIrp;
4945
4946 ASSERT(*(PULONG)deviceExtension != '2slc');
4947 ASSERT(*(PULONG)physicalExtension != '2slc');
4948
4949 originalIrp = irpStack->Parameters.Others.Argument1;
4950
4951 //
4952 // Copy the media change count and status
4953 //
4954
4955 *((PULONG) (originalIrp->AssociatedIrp.SystemBuffer)) =
4956 physicalExtension->MediaChangeCount;
4957
4958 DebugPrint((2, "ScsiClassInterpretSenseInfo - Media change count for"
4959 "device %d is %d\n",
4960 physicalExtension->DeviceNumber,
4961 physicalExtension->MediaChangeCount));
4962
4963 originalIrp->IoStatus.Status = Irp->IoStatus.Status;
4964 originalIrp->IoStatus.Information = sizeof(ULONG);
4965
4966 IoCompleteRequest(originalIrp, IO_DISK_INCREMENT);
4967
4968 IoFreeIrp(Irp);
4969
4970 return STATUS_MORE_PROCESSING_REQUIRED;
4971 }
4972
4973 NTSTATUS
4974 NTAPI
4975 ClassCompletionRoutine(IN PDEVICE_OBJECT DeviceObject,
4976 IN PIRP Irp,
4977 IN PVOID Context)
4978 {
4979 PIO_STATUS_BLOCK IoStatusBlock = Irp->UserIosb;
4980 PKEVENT Event = Irp->UserEvent;
4981 PMDL Mdl;
4982
4983 *IoStatusBlock = Irp->IoStatus;
4984 Irp->UserIosb = NULL;
4985 Irp->UserEvent = NULL;
4986
4987 if(Irp->MdlAddress)
4988 {
4989 Mdl = Irp->MdlAddress;
4990
4991 // if necessary - unlock pages
4992 if ((Mdl->MdlFlags & MDL_PAGES_LOCKED) &&
4993 !(Mdl->MdlFlags & MDL_PARTIAL_HAS_BEEN_MAPPED))
4994 {
4995 MmUnlockPages(Mdl);
4996 }
4997
4998 // free this mdl
4999 IoFreeMdl(Mdl);
5000 }
5001
5002 // free irp and set event to unsignaled state
5003 IoFreeIrp(Irp);
5004 KeSetEvent(Event, IO_NO_INCREMENT, FALSE);
5005
5006 return STATUS_MORE_PROCESSING_REQUIRED;
5007 }