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