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