ReactOS  0.4.14-dev-1338-g0d187f7
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 media capacity in bytes.
832  //
833 
834  deviceExtension->PartitionLength.QuadPart = (LONGLONG)(lastSector + 1);
835 
836  //
837  // Calculate number of cylinders.
838  //
839 
840  deviceExtension->DiskGeometry->Geometry.Cylinders.QuadPart = (LONGLONG)((lastSector + 1)/(DEFAULT_SECTORS_PER_TRACK * DEFAULT_TRACKS_PER_CYLINDER));
841 
842  deviceExtension->PartitionLength.QuadPart =
843  (deviceExtension->PartitionLength.QuadPart << deviceExtension->SectorShift);
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 
907  if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) {
908 
909  //
910  // This device supports removable media.
911  //
912 
913  deviceExtension->DiskGeometry->Geometry.MediaType = RemovableMedia;
914 
915  } else {
916 
917  //
918  // Assume media type is fixed disk.
919  //
920 
921  deviceExtension->DiskGeometry->Geometry.MediaType = FixedMedia;
922  }
923  }
924 
925  //
926  // Deallocate read capacity buffer.
927  //
928 
929  ExFreePool(readCapacityBuffer);
930 
931  return status;
932 
933 } // end ScsiClassReadDriveCapacity()
934 
935 
936 VOID
937 NTAPI
940  )
941 
942 /*++
943 
944 Routine Description:
945 
946  This routine issues an internal device control command
947  to the port driver to release a frozen queue. The call
948  is issued asynchronously as ScsiClassReleaseQueue will be invoked
949  from the IO completion DPC (and will have no context to
950  wait for a synchronous call to complete).
951 
952 Arguments:
953 
954  DeviceObject - The device object for the logical unit with
955  the frozen queue.
956 
957 Return Value:
958 
959  None.
960 
961 --*/
962 {
963  PIO_STACK_LOCATION irpStack;
964  PIRP irp;
968  KIRQL currentIrql;
969 
970  ASSERT(*(PULONG)deviceExtension != '2slc');
971 
972  //
973  // Allocate context from nonpaged pool.
974  //
975 
977  sizeof(COMPLETION_CONTEXT));
978 
979  //
980  // Save the device object in the context for use by the completion
981  // routine.
982  //
983 
984  context->DeviceObject = DeviceObject;
985  srb = &context->Srb;
986 
987  //
988  // Zero out srb.
989  //
990 
992 
993  //
994  // Write length to SRB.
995  //
996 
998 
999  //
1000  // Set up SCSI bus address.
1001  //
1002 
1003  srb->PathId = deviceExtension->PathId;
1004  srb->TargetId = deviceExtension->TargetId;
1005  srb->Lun = deviceExtension->Lun;
1006 
1007  //
1008  // If this device is removable then flush the queue. This will also
1009  // release it.
1010  //
1011 
1012  if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) {
1013 
1015 
1016  } else {
1017 
1019 
1020  }
1021 
1022  //
1023  // Build the asynchronous request to be sent to the port driver.
1024  //
1025 
1027 
1028  if(irp == NULL) {
1029 
1030  //
1031  // We have no better way of dealing with this at the moment
1032  //
1033 
1034  KeBugCheck((ULONG)0x0000002DL);
1035 
1036  }
1037 
1040  context,
1041  TRUE,
1042  TRUE,
1043  TRUE);
1044 
1045  irpStack = IoGetNextIrpStackLocation(irp);
1046 
1047  irpStack->MajorFunction = IRP_MJ_SCSI;
1048 
1049  srb->OriginalRequest = irp;
1050 
1051  //
1052  // Store the SRB address in next stack for port driver.
1053  //
1054 
1055  irpStack->Parameters.Scsi.Srb = srb;
1056 
1057  //
1058  // Since this routine can cause outstanding requests to be completed, and
1059  // calling a completion routine at < DISPATCH_LEVEL is dangerous (if they
1060  // call IoStartNextPacket we will bugcheck) raise up to dispatch level before
1061  // issuing the request
1062  //
1063 
1064  currentIrql = KeGetCurrentIrql();
1065 
1066  if(currentIrql < DISPATCH_LEVEL) {
1067  KeRaiseIrql(DISPATCH_LEVEL, &currentIrql);
1068  IoCallDriver(deviceExtension->PortDeviceObject, irp);
1069  KeLowerIrql(currentIrql);
1070  } else {
1071  IoCallDriver(deviceExtension->PortDeviceObject, irp);
1072  }
1073 
1074  return;
1075 
1076 } // end ScsiClassReleaseQueue()
1077 
1078 
1079 VOID
1080 NTAPI
1083  )
1084 
1085 /*++
1086 
1087 Routine Description:
1088 
1089  Send command to SCSI unit to start or power up.
1090  Because this command is issued asynchronously, that is, without
1091  waiting on it to complete, the IMMEDIATE flag is not set. This
1092  means that the CDB will not return until the drive has powered up.
1093  This should keep subsequent requests from being submitted to the
1094  device before it has completely spun up.
1095  This routine is called from the InterpretSense routine, when a
1096  request sense returns data indicating that a drive must be
1097  powered up.
1098 
1099 Arguments:
1100 
1101  DeviceObject - The device object for the logical unit with
1102  the frozen queue.
1103 
1104 Return Value:
1105 
1106  None.
1107 
1108 --*/
1109 {
1110  PIO_STACK_LOCATION irpStack;
1111  PIRP irp;
1112  PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
1113  PSCSI_REQUEST_BLOCK srb;
1115  PCDB cdb;
1116 
1117  ASSERT(*(PULONG)deviceExtension != '2slc');
1118 
1119  //
1120  // Allocate Srb from nonpaged pool.
1121  //
1122 
1124  sizeof(COMPLETION_CONTEXT));
1125 
1126  //
1127  // Save the device object in the context for use by the completion
1128  // routine.
1129  //
1130 
1131  context->DeviceObject = DeviceObject;
1132  srb = &context->Srb;
1133 
1134  //
1135  // Zero out srb.
1136  //
1137 
1139 
1140  //
1141  // Write length to SRB.
1142  //
1143 
1145 
1146  //
1147  // Set up SCSI bus address.
1148  //
1149 
1150  srb->PathId = deviceExtension->PathId;
1151  srb->TargetId = deviceExtension->TargetId;
1152  srb->Lun = deviceExtension->Lun;
1153 
1155 
1156  //
1157  // Set timeout value large enough for drive to spin up.
1158  //
1159 
1161 
1162  //
1163  // Set the transfer length.
1164  //
1165 
1167 
1168  //
1169  // Build the start unit CDB.
1170  //
1171 
1172  srb->CdbLength = 6;
1173  cdb = (PCDB)srb->Cdb;
1174 
1175  cdb->START_STOP.OperationCode = SCSIOP_START_STOP_UNIT;
1176  cdb->START_STOP.Start = 1;
1177  cdb->START_STOP.LogicalUnitNumber = srb->Lun;
1178 
1179  //
1180  // Build the asynchronous request to be sent to the port driver.
1181  // Since this routine is called from a DPC the IRP should always be
1182  // available.
1183  //
1184 
1188  context,
1189  TRUE,
1190  TRUE,
1191  TRUE);
1192 
1193  irpStack = IoGetNextIrpStackLocation(irp);
1194  irpStack->MajorFunction = IRP_MJ_SCSI;
1195  srb->OriginalRequest = irp;
1196 
1197  //
1198  // Store the SRB address in next stack for port driver.
1199  //
1200 
1201  irpStack->Parameters.Scsi.Srb = srb;
1202 
1203  //
1204  // Call the port driver with the IRP.
1205  //
1206 
1207  IoCallDriver(deviceExtension->PortDeviceObject, irp);
1208 
1209  return;
1210 
1211 } // end StartUnit()
1212 
1213 
1214 NTSTATUS
1215 NTAPI
1218  PIRP Irp,
1219  PVOID Context
1220  )
1221 /*++
1222 
1223 Routine Description:
1224 
1225  This routine is called when an asynchronous I/O request
1226  which was issued by the class driver completes. Examples of such requests
1227  are release queue or START UNIT. This routine releases the queue if
1228  necessary. It then frees the context and the IRP.
1229 
1230 Arguments:
1231 
1232  DeviceObject - The device object for the logical unit; however since this
1233  is the top stack location the value is NULL.
1234 
1235  Irp - Supplies a pointer to the Irp to be processed.
1236 
1237  Context - Supplies the context to be used to process this request.
1238 
1239 Return Value:
1240 
1241  None.
1242 
1243 --*/
1244 
1245 {
1247  PSCSI_REQUEST_BLOCK srb;
1248 
1249  srb = &context->Srb;
1250 
1251  //
1252  // If this is an execute srb, then check the return status and make sure.
1253  // the queue is not frozen.
1254  //
1255 
1256  if (srb->Function == SRB_FUNCTION_EXECUTE_SCSI) {
1257 
1258  //
1259  // Check for a frozen queue.
1260  //
1261 
1262  if (srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) {
1263 
1264  //
1265  // Unfreeze the queue getting the device object from the context.
1266  //
1267 
1268  ScsiClassReleaseQueue(context->DeviceObject);
1269  }
1270  }
1271 
1272  //
1273  // Free the context and the Irp.
1274  //
1275 
1276  if (Irp->MdlAddress != NULL) {
1277  MmUnlockPages(Irp->MdlAddress);
1278  IoFreeMdl(Irp->MdlAddress);
1279 
1280  Irp->MdlAddress = NULL;
1281  }
1282 
1284  IoFreeIrp(Irp);
1285 
1286  //
1287  // Indicate the I/O system should stop processing the Irp completion.
1288  //
1289 
1291 
1292 } // ScsiClassAsynchronousCompletion()
1293 
1294 
1295 VOID
1296 NTAPI
1299  IN PIRP Irp,
1300  IN ULONG MaximumBytes
1301  )
1302 
1303 /*++
1304 
1305 Routine Description:
1306 
1307  Break request into smaller requests. Each new request will be the
1308  maximum transfer size that the port driver can handle or if it
1309  is the final request, it may be the residual size.
1310 
1311  The number of IRPs required to process this request is written in the
1312  current stack of the original IRP. Then as each new IRP completes
1313  the count in the original IRP is decremented. When the count goes to
1314  zero, the original IRP is completed.
1315 
1316 Arguments:
1317 
1318  DeviceObject - Pointer to the class device object to be addressed.
1319 
1320  Irp - Pointer to Irp the original request.
1321 
1322 Return Value:
1323 
1324  None.
1325 
1326 --*/
1327 
1328 {
1329  PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
1332  ULONG transferByteCount = currentIrpStack->Parameters.Read.Length;
1333  LARGE_INTEGER startingOffset = currentIrpStack->Parameters.Read.ByteOffset;
1334  PVOID dataBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress);
1335  ULONG dataLength = MaximumBytes;
1336  ULONG irpCount = (transferByteCount + MaximumBytes - 1) / MaximumBytes;
1337  ULONG i;
1338  PSCSI_REQUEST_BLOCK srb;
1339 
1340  DebugPrint((2, "ScsiClassSplitRequest: Requires %d IRPs\n", irpCount));
1341  DebugPrint((2, "ScsiClassSplitRequest: Original IRP %lx\n", Irp));
1342 
1343  ASSERT(*(PULONG)deviceExtension != '2slc');
1344 
1345  //
1346  // If all partial transfers complete successfully then the status and
1347  // bytes transferred are already set up. Failing a partial-transfer IRP
1348  // will set status to error and bytes transferred to 0 during
1349  // IoCompletion. Setting bytes transferred to 0 if an IRP fails allows
1350  // asynchronous partial transfers. This is an optimization for the
1351  // successful case.
1352  //
1353 
1354  Irp->IoStatus.Status = STATUS_SUCCESS;
1355  Irp->IoStatus.Information = transferByteCount;
1356 
1357  //
1358  // Save number of IRPs to complete count on current stack
1359  // of original IRP.
1360  //
1361 
1362  nextIrpStack->Parameters.Others.Argument1 = (PVOID)(ULONG_PTR) irpCount;
1363 
1364  for (i = 0; i < irpCount; i++) {
1365 
1366  PIRP newIrp;
1367  PIO_STACK_LOCATION newIrpStack;
1368 
1369  //
1370  // Allocate new IRP.
1371  //
1372 
1374 
1375  if (newIrp == NULL) {
1376 
1377  DebugPrint((1,"ScsiClassSplitRequest: Can't allocate Irp\n"));
1378 
1379  //
1380  // If an Irp can't be allocated then the original request cannot
1381  // be executed. If this is the first request then just fail the
1382  // original request; otherwise just return. When the pending
1383  // requests complete, they will complete the original request.
1384  // In either case set the IRP status to failure.
1385  //
1386 
1387  Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
1388  Irp->IoStatus.Information = 0;
1389 
1390  if (i == 0) {
1392  }
1393 
1394  return;
1395  }
1396 
1397  DebugPrint((2, "ScsiClassSplitRequest: New IRP %lx\n", newIrp));
1398 
1399  //
1400  // Write MDL address to new IRP. In the port driver the SRB data
1401  // buffer field is used as an offset into the MDL, so the same MDL
1402  // can be used for each partial transfer. This saves having to build
1403  // a new MDL for each partial transfer.
1404  //
1405 
1406  newIrp->MdlAddress = Irp->MdlAddress;
1407 
1408  //
1409  // At this point there is no current stack. IoSetNextIrpStackLocation
1410  // will make the first stack location the current stack so that the
1411  // SRB address can be written there.
1412  //
1413 
1414  IoSetNextIrpStackLocation(newIrp);
1415  newIrpStack = IoGetCurrentIrpStackLocation(newIrp);
1416 
1417  newIrpStack->MajorFunction = currentIrpStack->MajorFunction;
1418  newIrpStack->Parameters.Read.Length = dataLength;
1419  newIrpStack->Parameters.Read.ByteOffset = startingOffset;
1420  newIrpStack->DeviceObject = DeviceObject;
1421 
1422  //
1423  // Build SRB and CDB.
1424  //
1425 
1427 
1428  //
1429  // Adjust SRB for this partial transfer.
1430  //
1431 
1432  newIrpStack = IoGetNextIrpStackLocation(newIrp);
1433 
1434  srb = newIrpStack->Parameters.Others.Argument1;
1435  srb->DataBuffer = dataBuffer;
1436 
1437  //
1438  // Write original IRP address to new IRP.
1439  //
1440 
1441  newIrp->AssociatedIrp.MasterIrp = Irp;
1442 
1443  //
1444  // Set the completion routine to ScsiClassIoCompleteAssociated.
1445  //
1446 
1447  IoSetCompletionRoutine(newIrp,
1449  srb,
1450  TRUE,
1451  TRUE,
1452  TRUE);
1453 
1454  //
1455  // Call port driver with new request.
1456  //
1457 
1458  IoCallDriver(deviceExtension->PortDeviceObject, newIrp);
1459 
1460  //
1461  // Set up for next request.
1462  //
1463 
1464  dataBuffer = (PCHAR)dataBuffer + MaximumBytes;
1465 
1466  transferByteCount -= MaximumBytes;
1467 
1468  if (transferByteCount > MaximumBytes) {
1469 
1470  dataLength = MaximumBytes;
1471 
1472  } else {
1473 
1474  dataLength = transferByteCount;
1475  }
1476 
1477  //
1478  // Adjust disk byte offset.
1479  //
1480 
1481  startingOffset.QuadPart = startingOffset.QuadPart + MaximumBytes;
1482  }
1483 
1484  return;
1485 
1486 } // end ScsiClassSplitRequest()
1487 
1488 
1489 NTSTATUS
1490 NTAPI
1493  IN PIRP Irp,
1494  IN PVOID Context
1495  )
1496 
1497 /*++
1498 
1499 Routine Description:
1500 
1501  This routine executes when the port driver has completed a request.
1502  It looks at the SRB status in the completing SRB and if not success
1503  it checks for valid request sense buffer information. If valid, the
1504  info is used to update status with more precise message of type of
1505  error. This routine deallocates the SRB.
1506 
1507 Arguments:
1508 
1509  DeviceObject - Supplies the device object which represents the logical
1510  unit.
1511 
1512  Irp - Supplies the Irp which has completed.
1513 
1514  Context - Supplies a pointer to the SRB.
1515 
1516 Return Value:
1517 
1518  NT status
1519 
1520 --*/
1521 
1522 {
1525  PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
1526  NTSTATUS status;
1527  BOOLEAN retry;
1528 
1529  ASSERT(*(PULONG)deviceExtension != '2slc');
1530 
1531  //
1532  // Check SRB status for success of completing request.
1533  //
1534 
1535  if (SRB_STATUS(srb->SrbStatus) != SRB_STATUS_SUCCESS) {
1536 
1537  DebugPrint((2,"ScsiClassIoComplete: IRP %lx, SRB %lx\n", Irp, srb));
1538 
1539  //
1540  // Release the queue if it is frozen.
1541  //
1542 
1543  if (srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) {
1545  }
1546 
1548  DeviceObject,
1549  srb,
1550  irpStack->MajorFunction,
1551  irpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL ? irpStack->Parameters.DeviceIoControl.IoControlCode : 0,
1552  MAXIMUM_RETRIES - PtrToUlong(irpStack->Parameters.Others.Argument4),
1553  &status);
1554 
1555  //
1556  // If the status is verified required and the this request
1557  // should bypass verify required then retry the request.
1558  //
1559 
1560  if (irpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME &&
1562 
1564  retry = TRUE;
1565  }
1566 
1567  if (retry && (irpStack->Parameters.Others.Argument4 = (PVOID)((ULONG_PTR)irpStack->Parameters.Others.Argument4-1))) {
1568 
1569  //
1570  // Retry request.
1571  //
1572 
1573  DebugPrint((1, "Retry request %lx\n", Irp));
1576  }
1577  } else {
1578 
1579  //
1580  // Set status for successful request.
1581  //
1582 
1584 
1585  } // end if (SRB_STATUS(srb->SrbStatus) ...
1586 
1587  //
1588  // Return SRB to list.
1589  //
1590 
1591  ExFreeToNPagedLookasideList(&deviceExtension->SrbLookasideListHead,
1592  srb);
1593 
1594  //
1595  // Set status in completing IRP.
1596  //
1597 
1598  Irp->IoStatus.Status = status;
1599  if ((NT_SUCCESS(status)) && (Irp->Flags & IRP_PAGING_IO)) {
1600  ASSERT(Irp->IoStatus.Information);
1601  }
1602 
1603  //
1604  // Set the hard error if necessary.
1605  //
1606 
1608 
1609  //
1610  // Store DeviceObject for filesystem, and clear
1611  // in IoStatus.Information field.
1612  //
1613 
1615  Irp->IoStatus.Information = 0;
1616  }
1617 
1618  //
1619  // If pending has be returned for this irp then mark the current stack as
1620  // pending.
1621  //
1622 
1623  if (Irp->PendingReturned) {
1625  }
1626 
1627  if (deviceExtension->ClassStartIo) {
1628  if (irpStack->MajorFunction != IRP_MJ_DEVICE_CONTROL) {
1630  }
1631  }
1632 
1633  return status;
1634 
1635 } // end ScsiClassIoComplete()
1636 
1637 
1638 NTSTATUS
1639 NTAPI
1642  IN PIRP Irp,
1643  IN PVOID Context
1644  )
1645 
1646 /*++
1647 
1648 Routine Description:
1649 
1650  This routine executes when the port driver has completed a request.
1651  It looks at the SRB status in the completing SRB and if not success
1652  it checks for valid request sense buffer information. If valid, the
1653  info is used to update status with more precise message of type of
1654  error. This routine deallocates the SRB. This routine is used for
1655  requests which were build by split request. After it has processed
1656  the request it decrements the Irp count in the master Irp. If the
1657  count goes to zero then the master Irp is completed.
1658 
1659 Arguments:
1660 
1661  DeviceObject - Supplies the device object which represents the logical
1662  unit.
1663 
1664  Irp - Supplies the Irp which has completed.
1665 
1666  Context - Supplies a pointer to the SRB.
1667 
1668 Return Value:
1669 
1670  NT status
1671 
1672 --*/
1673 
1674 {
1677  PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
1678  PIRP originalIrp = Irp->AssociatedIrp.MasterIrp;
1679  LONG irpCount;
1680  NTSTATUS status;
1681  BOOLEAN retry;
1682 
1683  ASSERT(*(PULONG)deviceExtension != '2slc');
1684 
1685  //
1686  // Check SRB status for success of completing request.
1687  //
1688 
1689  if (SRB_STATUS(srb->SrbStatus) != SRB_STATUS_SUCCESS) {
1690 
1691  DebugPrint((2,"ScsiClassIoCompleteAssociated: IRP %lx, SRB %lx", Irp, srb));
1692 
1693  //
1694  // Release the queue if it is frozen.
1695  //
1696 
1697  if (srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) {
1699  }
1700 
1702  DeviceObject,
1703  srb,
1704  irpStack->MajorFunction,
1705  irpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL ? irpStack->Parameters.DeviceIoControl.IoControlCode : 0,
1706  MAXIMUM_RETRIES - PtrToUlong(irpStack->Parameters.Others.Argument4),
1707  &status);
1708 
1709  //
1710  // If the status is verified required and the this request
1711  // should bypass verify required then retry the request.
1712  //
1713 
1714  if (irpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME &&
1716 
1718  retry = TRUE;
1719  }
1720 
1721  if (retry && (irpStack->Parameters.Others.Argument4 = (PVOID)((ULONG_PTR)irpStack->Parameters.Others.Argument4-1))) {
1722 
1723  //
1724  // Retry request. If the class driver has supplied a StartIo,
1725  // call it directly for retries.
1726  //
1727 
1728  DebugPrint((1, "Retry request %lx\n", Irp));
1729 
1730  /*
1731  if (!deviceExtension->ClassStartIo) {
1732  RetryRequest(DeviceObject, Irp, srb, TRUE);
1733  } else {
1734  deviceExtension->ClassStartIo(DeviceObject, Irp);
1735  }
1736  */
1737 
1739 
1741  }
1742 
1743 
1744 
1745  } else {
1746 
1747  //
1748  // Set status for successful request.
1749  //
1750 
1752 
1753  } // end if (SRB_STATUS(srb->SrbStatus) ...
1754 
1755  //
1756  // Return SRB to list.
1757  //
1758 
1759  ExFreeToNPagedLookasideList(&deviceExtension->SrbLookasideListHead,
1760  srb);
1761 
1762  //
1763  // Set status in completing IRP.
1764  //
1765 
1766  Irp->IoStatus.Status = status;
1767 
1768  DebugPrint((2, "ScsiClassIoCompleteAssociated: Partial xfer IRP %lx\n", Irp));
1769 
1770  //
1771  // Get next stack location. This original request is unused
1772  // except to keep track of the completing partial IRPs so the
1773  // stack location is valid.
1774  //
1775 
1776  irpStack = IoGetNextIrpStackLocation(originalIrp);
1777 
1778  //
1779  // Update status only if error so that if any partial transfer
1780  // completes with error, then the original IRP will return with
1781  // error. If any of the asynchronous partial transfer IRPs fail,
1782  // with an error then the original IRP will return 0 bytes transfered.
1783  // This is an optimization for successful transfers.
1784  //
1785 
1786  if (!NT_SUCCESS(status)) {
1787 
1788  originalIrp->IoStatus.Status = status;
1789  originalIrp->IoStatus.Information = 0;
1790 
1791  //
1792  // Set the hard error if necessary.
1793  //
1794 
1796 
1797  //
1798  // Store DeviceObject for filesystem.
1799  //
1800 
1802  }
1803  }
1804 
1805  //
1806  // Decrement and get the count of remaining IRPs.
1807  //
1808 
1809  irpCount = InterlockedDecrement((PLONG)&irpStack->Parameters.Others.Argument1);
1810 
1811  DebugPrint((2, "ScsiClassIoCompleteAssociated: Partial IRPs left %d\n",
1812  irpCount));
1813 
1814  //
1815  // Old bug could cause irp count to negative
1816  //
1817 
1818  ASSERT(irpCount >= 0);
1819 
1820  if (irpCount == 0) {
1821 
1822  //
1823  // All partial IRPs have completed.
1824  //
1825 
1826  DebugPrint((2,
1827  "ScsiClassIoCompleteAssociated: All partial IRPs complete %lx\n",
1828  originalIrp));
1829 
1830  IoCompleteRequest(originalIrp, IO_DISK_INCREMENT);
1831 
1832  //
1833  // If the class driver has supplied a startio, start the
1834  // next request.
1835  //
1836 
1837  if (deviceExtension->ClassStartIo) {
1839  }
1840  }
1841 
1842  //
1843  // Deallocate IRP and indicate the I/O system should not attempt any more
1844  // processing.
1845  //
1846 
1847  IoFreeIrp(Irp);
1849 
1850 } // end ScsiClassIoCompleteAssociated()
1851 
1852 
1853 NTSTATUS
1854 NTAPI
1858  PVOID BufferAddress,
1860  BOOLEAN WriteToDevice
1861  )
1862 
1863 /*++
1864 
1865 Routine Description:
1866 
1867  This routine is called by SCSI device controls to complete an
1868  SRB and send it to the port driver synchronously (ie wait for
1869  completion). The CDB is already completed along with the SRB CDB
1870  size and request timeout value.
1871 
1872 Arguments:
1873 
1874  DeviceObject - Supplies the device object which represents the logical
1875  unit.
1876 
1877  Srb - Supplies a partially initialized SRB. The SRB cannot come from zone.
1878 
1879  BufferAddress - Supplies the address of the buffer.
1880 
1881  BufferLength - Supplies the length in bytes of the buffer.
1882 
1883  WriteToDevice - Indicates the data should be transfer to the device.
1884 
1885 Return Value:
1886 
1887  Nt status indicating the final results of the operation.
1888 
1889 --*/
1890 
1891 {
1892  PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
1893  IO_STATUS_BLOCK ioStatus;
1894  ULONG controlType, mjFunction;
1895  PIRP irp;
1896  PIO_STACK_LOCATION irpStack;
1897  KEVENT event;
1898  PUCHAR senseInfoBuffer;
1899  ULONG retryCount = MAXIMUM_RETRIES;
1900  NTSTATUS status;
1901  BOOLEAN retry;
1903 
1904  PAGED_CODE();
1905 
1906  ASSERT(*(PULONG)deviceExtension != '2slc');
1907 
1908  dummy.QuadPart = 0;
1909 
1910  //
1911  // Write length to SRB.
1912  //
1913 
1914  Srb->Length = SCSI_REQUEST_BLOCK_SIZE;
1915 
1916  //
1917  // Set SCSI bus address.
1918  //
1919 
1920  Srb->PathId = deviceExtension->PathId;
1921  Srb->TargetId = deviceExtension->TargetId;
1922  Srb->Lun = deviceExtension->Lun;
1923  Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
1924 
1925  //
1926  // NOTICE: The SCSI-II specification indicates that this field should be
1927  // zero; however, some target controllers ignore the logical unit number
1928  // in the IDENTIFY message and only look at the logical unit number field
1929  // in the CDB.
1930  //
1931 
1932  Srb->Cdb[1] |= deviceExtension->Lun << 5;
1933 
1934  //
1935  // Enable auto request sense.
1936  //
1937 
1938  Srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE;
1939 
1940  //
1941  // Sense buffer is in aligned nonpaged pool.
1942  //
1943 
1945 
1946  if (senseInfoBuffer == NULL) {
1947 
1948  DebugPrint((1,
1949  "ScsiClassSendSrbSynchronous: Can't allocate request sense buffer\n"));
1951  }
1952 
1953  Srb->SenseInfoBuffer = senseInfoBuffer;
1954  Srb->DataBuffer = BufferAddress;
1955 
1956  //
1957  // Start retries here.
1958  //
1959 
1960 retry:
1961 
1962  //
1963  // Set the event object to the unsignaled state.
1964  // It will be used to signal request completion.
1965  //
1966 
1968 
1969  //
1970  // Set controlType and Srb direction flags.
1971  //
1972 
1973  if (BufferAddress != NULL) {
1974 
1975  if (WriteToDevice) {
1976 
1977  controlType = IOCTL_SCSI_EXECUTE_OUT;
1978  Srb->SrbFlags = SRB_FLAGS_DATA_OUT;
1979  mjFunction = IRP_MJ_WRITE;
1980 
1981  } else {
1982 
1983  controlType = IOCTL_SCSI_EXECUTE_IN;
1984  Srb->SrbFlags = SRB_FLAGS_DATA_IN;
1985  mjFunction = IRP_MJ_READ;
1986  }
1987 
1988  } else {
1989 
1990  BufferLength = 0;
1991  controlType = IOCTL_SCSI_EXECUTE_NONE;
1992  Srb->SrbFlags = SRB_FLAGS_NO_DATA_TRANSFER;
1993  mjFunction = IRP_MJ_FLUSH_BUFFERS;
1994  }
1995 
1996  //
1997  // Build device I/O control request with data transfer.
1998  //
2000  mjFunction,
2001  deviceExtension->DeviceObject,
2002  BufferAddress,
2003  (BufferAddress) ? BufferLength : 0,
2004  &dummy,
2005  &ioStatus);
2006 
2007  if (irp == NULL) {
2008  ExFreePool(senseInfoBuffer);
2009  DebugPrint((1, "ScsiClassSendSrbSynchronous: Can't allocate Irp\n"));
2011  }
2012 
2013  // Set event field
2014  irp->UserEvent = &event;
2015 
2016  //
2017  // Disable synchronous transfer for these requests.
2018  //
2019 
2021 
2022  //
2023  // Set the transfer length.
2024  //
2025 
2026  Srb->DataTransferLength = BufferLength;
2027 
2028  //
2029  // Zero out status.
2030  //
2031 
2032  Srb->ScsiStatus = Srb->SrbStatus = 0;
2033  Srb->NextSrb = 0;
2034 
2035  // Set completion routine
2037  irp,
2039  NULL,
2040  TRUE,
2041  TRUE,
2042  TRUE);
2043 
2044  //
2045  // Get next stack location.
2046  //
2047 
2048  irpStack = IoGetNextIrpStackLocation(irp);
2049 
2051  irpStack->Parameters.DeviceIoControl.IoControlCode = controlType;
2052 
2053  //
2054  // Set up SRB for execute scsi request. Save SRB address in next stack
2055  // for the port driver.
2056  //
2057 
2058  irpStack->Parameters.Scsi.Srb = Srb;
2059 
2060  //
2061  // Set up IRP Address.
2062  //
2063 
2064  Srb->OriginalRequest = irp;
2065 
2066  //
2067  // Call the port driver with the request and wait for it to complete.
2068  //
2069 
2070  status = IoCallDriver(deviceExtension->PortDeviceObject, irp);
2071 
2072  if (status == STATUS_PENDING) {
2074  }
2075 
2076  //
2077  // Check that request completed without error.
2078  //
2079 
2080  if (SRB_STATUS(Srb->SrbStatus) != SRB_STATUS_SUCCESS) {
2081 
2082  //
2083  // Release the queue if it is frozen.
2084  //
2085 
2086  if (Srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) {
2088  }
2089 
2090  //
2091  // Update status and determine if request should be retried.
2092  //
2093 
2095  Srb,
2096  IRP_MJ_SCSI,
2097  0,
2098  MAXIMUM_RETRIES - retryCount,
2099  &status);
2100 
2101  if (retry) {
2102 
2103  if ((status == STATUS_DEVICE_NOT_READY && ((PSENSE_DATA) senseInfoBuffer)
2104  ->AdditionalSenseCode == SCSI_ADSENSE_LUN_NOT_READY) ||
2105  SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_SELECTION_TIMEOUT) {
2106 
2107  LARGE_INTEGER delay;
2108 
2109  //
2110  // Delay for 2 seconds.
2111  //
2112 
2113  delay.QuadPart = (LONGLONG)( - 10 * 1000 * 1000 * 2 );
2114 
2115  //
2116  // Stall for a while to let the controller spinup.
2117  //
2118 
2120  FALSE,
2121  &delay);
2122 
2123  }
2124 
2125  //
2126  // If retries are not exhausted then retry this operation.
2127  //
2128 
2129  if (retryCount--) {
2130  goto retry;
2131  }
2132  }
2133 
2134  } else {
2135 
2137  }
2138 
2139  ExFreePool(senseInfoBuffer);
2140  return status;
2141 
2142 } // end ScsiClassSendSrbSynchronous()
2143 
2144 
2145 BOOLEAN
2146 NTAPI
2152  IN ULONG RetryCount,
2154  )
2155 
2156 /*++
2157 
2158 Routine Description:
2159 
2160  This routine interprets the data returned from the SCSI
2161  request sense. It determines the status to return in the
2162  IRP and whether this request can be retried.
2163 
2164 Arguments:
2165 
2166  DeviceObject - Supplies the device object associated with this request.
2167 
2168  Srb - Supplies the scsi request block which failed.
2169 
2170  MajorFunctionCode - Supplies the function code to be used for logging.
2171 
2172  IoDeviceCode - Supplies the device code to be used for logging.
2173 
2174  Status - Returns the status for the request.
2175 
2176 Return Value:
2177 
2178  BOOLEAN TRUE: Drivers should retry this request.
2179  FALSE: Drivers should not retry this request.
2180 
2181 --*/
2182 
2183 {
2184  PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
2185  PDEVICE_EXTENSION physicalExtension = deviceExtension->PhysicalDevice->DeviceExtension;
2186  PSENSE_DATA senseBuffer = Srb->SenseInfoBuffer;
2187  BOOLEAN retry = TRUE;
2188  BOOLEAN logError = FALSE;
2189  ULONG badSector = 0;
2190  ULONG uniqueId = 0;
2191  NTSTATUS logStatus;
2192  ULONG readSector;
2193  ULONG index;
2194  PIO_ERROR_LOG_PACKET errorLogEntry;
2195 #if DBG
2196  ULONG i;
2197 #endif
2198 
2199  ASSERT(*(PULONG)deviceExtension != '2slc');
2200 
2201  //
2202  // Check that request sense buffer is valid.
2203  //
2204 
2205 #if DBG
2206  DebugPrint((3, "Opcode %x\nParameters: ",Srb->Cdb[0]));
2207  for (i = 1; i < 12; i++) {
2208  DebugPrint((3,"%x ",Srb->Cdb[i]));
2209  }
2210  DebugPrint((3,"\n"));
2211 #endif
2212 
2213  if (Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID &&
2214  Srb->SenseInfoBufferLength >= FIELD_OFFSET(SENSE_DATA, CommandSpecificInformation)) {
2215 
2216  DebugPrint((1,"ScsiClassInterpretSenseInfo: Error code is %x\n",
2217  senseBuffer->ErrorCode));
2218  DebugPrint((1,"ScsiClassInterpretSenseInfo: Sense key is %x\n",
2219  senseBuffer->SenseKey));
2220  DebugPrint((1, "ScsiClassInterpretSenseInfo: Additional sense code is %x\n",
2221  senseBuffer->AdditionalSenseCode));
2222  DebugPrint((1, "ScsiClassInterpretSenseInfo: Additional sense code qualifier is %x\n",
2223  senseBuffer->AdditionalSenseCodeQualifier));
2224 
2225  //
2226  // Zero the additional sense code and additional sense code qualifier
2227  // if they were not returned by the device.
2228  //
2229 
2230  readSector = senseBuffer->AdditionalSenseLength +
2231  FIELD_OFFSET(SENSE_DATA, AdditionalSenseLength);
2232 
2233  if (readSector > Srb->SenseInfoBufferLength) {
2234  readSector = Srb->SenseInfoBufferLength;
2235  }
2236 
2237  if (readSector <= FIELD_OFFSET(SENSE_DATA, AdditionalSenseCode)) {
2238  senseBuffer->AdditionalSenseCode = 0;
2239  }
2240 
2241  if (readSector <= FIELD_OFFSET(SENSE_DATA, AdditionalSenseCodeQualifier)) {
2242  senseBuffer->AdditionalSenseCodeQualifier = 0;
2243  }
2244 
2245  switch (senseBuffer->SenseKey & 0xf) {
2246 
2247  case SCSI_SENSE_NOT_READY:
2248 
2249  DebugPrint((1,"ScsiClassInterpretSenseInfo: Device not ready\n"));
2251 
2252  switch (senseBuffer->AdditionalSenseCode) {
2253 
2255 
2256  DebugPrint((1,"ScsiClassInterpretSenseInfo: Lun not ready\n"));
2257 
2258  switch (senseBuffer->AdditionalSenseCodeQualifier) {
2259 
2261 
2262  DebugPrint((1, "ScsiClassInterpretSenseInfo:"
2263  " In process of becoming ready\n"));
2264  break;
2265 
2267 
2268  DebugPrint((1, "ScsiClassInterpretSenseInfo:"
2269  " Manual intervention required\n"));
2271  retry = FALSE;
2272  break;
2273 
2275 
2276  DebugPrint((1, "ScsiClassInterpretSenseInfo: Format in progress\n"));
2277  retry = FALSE;
2278  break;
2279 
2281 
2282  default:
2283 
2284  DebugPrint((1, "ScsiClassInterpretSenseInfo:"
2285  " Initializing command required\n"));
2286 
2287  //
2288  // This sense code/additional sense code
2289  // combination may indicate that the device
2290  // needs to be started. Send an start unit if this
2291  // is a disk device.
2292  //
2293 
2294  if (deviceExtension->DeviceFlags & DEV_SAFE_START_UNIT) {
2296  }
2297 
2298  break;
2299 
2300  } // end switch (senseBuffer->AdditionalSenseCodeQualifier)
2301 
2302  break;
2303 
2305 
2306  DebugPrint((1,
2307  "ScsiClassInterpretSenseInfo:"
2308  " No Media in device.\n"));
2310  retry = FALSE;
2311 
2312  //
2313  // signal autorun that there isn't any media in the device
2314  //
2315 
2316  if((deviceExtension->MediaChangeEvent != NULL)&&
2317  (!deviceExtension->MediaChangeNoMedia)) {
2318  KeSetEvent(deviceExtension->MediaChangeEvent,
2319  (KPRIORITY) 0,
2320  FALSE);
2321  DebugPrint((0, "ScsiClassInterpretSenseInfo:"
2322  "Detected No Media In Device "
2323  "[irp = 0x%lx]\n", Srb->OriginalRequest));
2324  deviceExtension->MediaChangeNoMedia = TRUE;
2325  }
2326 
2327  break;
2328  } // end switch (senseBuffer->AdditionalSenseCode)
2329 
2330  break;
2331 
2333 
2334  DebugPrint((1, "ScsiClassInterpretSenseInfo: Media write protected\n"));
2336  retry = FALSE;
2337  break;
2338 
2340 
2341  DebugPrint((1,"ScsiClassInterpretSenseInfo: Bad media\n"));
2343 
2344  retry = FALSE;
2345  logError = TRUE;
2346  uniqueId = 256;
2347  logStatus = 0;//IO_ERR_BAD_BLOCK;
2348  break;
2349 
2351 
2352  DebugPrint((1,"ScsiClassInterpretSenseInfo: Hardware error\n"));
2354 
2355  logError = TRUE;
2356  uniqueId = 257;
2357  logStatus = 0;//IO_ERR_CONTROLLER_ERROR;
2358 
2359  break;
2360 
2362 
2363  DebugPrint((1, "ScsiClassInterpretSenseInfo: Illegal SCSI request\n"));
2365 
2366  switch (senseBuffer->AdditionalSenseCode) {
2367 
2369  DebugPrint((1, "ScsiClassInterpretSenseInfo: Illegal command\n"));
2370  retry = FALSE;
2371  break;
2372 
2374  DebugPrint((1, "ScsiClassInterpretSenseInfo: Illegal block address\n"));
2376  retry = FALSE;
2377  break;
2378 
2380  DebugPrint((1,"ScsiClassInterpretSenseInfo: Invalid LUN\n"));
2382  retry = FALSE;
2383  break;
2384 
2386  DebugPrint((1,"ScsiClassInterpretSenseInfo: Music area\n"));
2387  retry = FALSE;
2388  break;
2389 
2391  DebugPrint((1,"ScsiClassInterpretSenseInfo: Data area\n"));
2392  retry = FALSE;
2393  break;
2394 
2396  DebugPrint((1, "ScsiClassInterpretSenseInfo: Volume overflow\n"));
2397  retry = FALSE;
2398  break;
2399 
2401  DebugPrint((1, "ScsiClassInterpretSenseInfo: Invalid CDB\n"));
2402 
2403  //
2404  // Check if write cache enabled.
2405  //
2406 
2407  if (deviceExtension->DeviceFlags & DEV_WRITE_CACHE) {
2408 
2409  //
2410  // Assume FUA is not supported.
2411  //
2412 
2413  deviceExtension->DeviceFlags &= ~DEV_WRITE_CACHE;
2414  retry = TRUE;
2415 
2416  } else {
2417  retry = FALSE;
2418  }
2419 
2420  break;
2421 
2422  } // end switch (senseBuffer->AdditionalSenseCode)
2423 
2424  break;
2425 
2427 
2428  switch (senseBuffer->AdditionalSenseCode) {
2430  DebugPrint((1, "ScsiClassInterpretSenseInfo: Media changed\n"));
2431 
2432  if(deviceExtension->MediaChangeEvent != NULL) {
2433 
2434  KeSetEvent(deviceExtension->MediaChangeEvent,
2435  (KPRIORITY) 0,
2436  FALSE);
2437  DebugPrint((0, "ScsiClassInterpretSenseInfo:"
2438  "New Media Found - Setting MediaChanged event"
2439  " [irp = 0x%lx]\n", Srb->OriginalRequest));
2440  deviceExtension->MediaChangeNoMedia = FALSE;
2441 
2442  }
2443  break;
2444 
2446  DebugPrint((1,"ScsiClassInterpretSenseInfo: Bus reset\n"));
2447  break;
2448 
2449  default:
2450  DebugPrint((1,"ScsiClassInterpretSenseInfo: Unit attention\n"));
2451  break;
2452 
2453  } // end switch (senseBuffer->AdditionalSenseCode)
2454 
2455  if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA &&
2456  DeviceObject->Vpb->Flags & VPB_MOUNTED) {
2457 
2458  //
2459  // Set bit to indicate that media may have changed
2460  // and volume needs verification.
2461  //
2462 
2464 
2466  retry = FALSE;
2467 
2468  } else {
2469 
2471 
2472  }
2473 
2474  //
2475  // A media change may have occured so increment the change
2476  // count for the physical device
2477  //
2478 
2479  physicalExtension->MediaChangeCount++;
2480 
2481  DebugPrint((2, "ScsiClassInterpretSenseInfo - Media change "
2482  "count for device %d is %d\n",
2483  physicalExtension->DeviceNumber,
2484  physicalExtension->MediaChangeCount));
2485 
2486  break;
2487 
2489 
2490  DebugPrint((1,"ScsiClassInterpretSenseInfo: Command aborted\n"));
2492  break;
2493 
2495 
2496  DebugPrint((1,"ScsiClassInterpretSenseInfo: Recovered error\n"));
2498  retry = FALSE;
2499  logError = TRUE;
2500  uniqueId = 258;
2501 
2502  switch(senseBuffer->AdditionalSenseCode) {
2505  logStatus = 0;//IO_ERR_SEEK_ERROR;
2506  break;
2507 
2510  logStatus = 0;//IO_RECOVERED_VIA_ECC;
2511  break;
2512 
2513  default:
2514  logStatus = 0;//IO_ERR_CONTROLLER_ERROR;
2515  break;
2516 
2517  } // end switch(senseBuffer->AdditionalSenseCode)
2518 
2519  if (senseBuffer->IncorrectLength) {
2520 
2521  DebugPrint((1, "ScsiClassInterpretSenseInfo: Incorrect length detected.\n"));
2523  }
2524 
2525  break;
2526 
2527  case SCSI_SENSE_NO_SENSE:
2528 
2529  //
2530  // Check other indicators.
2531  //
2532 
2533  if (senseBuffer->IncorrectLength) {
2534 
2535  DebugPrint((1, "ScsiClassInterpretSenseInfo: Incorrect length detected.\n"));
2537  retry = FALSE;
2538 
2539  } else {
2540 
2541  DebugPrint((1, "ScsiClassInterpretSenseInfo: No specific sense key\n"));
2543  retry = TRUE;
2544  }
2545 
2546  break;
2547 
2548  default:
2549 
2550  DebugPrint((1, "ScsiClassInterpretSenseInfo: Unrecognized sense code\n"));
2552  break;
2553 
2554  } // end switch (senseBuffer->SenseKey & 0xf)
2555 
2556  //
2557  // Try to determine the bad sector from the inquiry data.
2558  //
2559 
2560  if ((((PCDB)Srb->Cdb)->CDB10.OperationCode == SCSIOP_READ ||
2561  ((PCDB)Srb->Cdb)->CDB10.OperationCode == SCSIOP_VERIFY ||
2562  ((PCDB)Srb->Cdb)->CDB10.OperationCode == SCSIOP_WRITE)) {
2563 
2564  for (index = 0; index < 4; index++) {
2565  badSector = (badSector << 8) | senseBuffer->Information[index];
2566  }
2567 
2568  readSector = 0;
2569  for (index = 0; index < 4; index++) {
2570  readSector = (readSector << 8) | Srb->Cdb[index+2];
2571  }
2572 
2573  index = (((PCDB)Srb->Cdb)->CDB10.TransferBlocksMsb << 8) |
2574  ((PCDB)Srb->Cdb)->CDB10.TransferBlocksLsb;
2575 
2576  //
2577  // Make sure the bad sector is within the read sectors.
2578  //
2579 
2580  if (!(badSector >= readSector && badSector < readSector + index)) {
2581  badSector = readSector;
2582  }
2583  }
2584 
2585  } else {
2586 
2587  //
2588  // Request sense buffer not valid. No sense information
2589  // to pinpoint the error. Return general request fail.
2590  //
2591 
2592  DebugPrint((1,"ScsiClassInterpretSenseInfo: Request sense info not valid. SrbStatus %2x\n",
2593  SRB_STATUS(Srb->SrbStatus)));
2594  retry = TRUE;
2595 
2596  switch (SRB_STATUS(Srb->SrbStatus)) {
2599  case SRB_STATUS_NO_DEVICE:
2600  case SRB_STATUS_NO_HBA:
2603  retry = FALSE;
2604  break;
2605 
2607  case SRB_STATUS_ABORTED:
2608  case SRB_STATUS_TIMEOUT:
2609 
2610  //
2611  // Update the error count for the device.
2612  //
2613 
2614  deviceExtension->ErrorCount++;
2616  break;
2617 
2619  logError = TRUE;
2620  logStatus = 0;//IO_ERR_NOT_READY;
2621  uniqueId = 260;
2623  retry = FALSE;
2624  break;
2625 
2628  retry = FALSE;
2629  break;
2630 
2632 
2633  //
2634  // Update the error count for the device.
2635  //
2636 
2637  deviceExtension->ErrorCount++;
2639 
2640  //
2641  // If there was phase sequence error then limit the number of
2642  // retries.
2643  //
2644 
2645  if (RetryCount > 1 ) {
2646  retry = FALSE;
2647  }
2648 
2649  break;
2650 
2652 
2653  //
2654  // If the status needs verification bit is set. Then set
2655  // the status to need verification and no retry; otherwise,
2656  // just retry the request.
2657  //
2658 
2660 
2662  retry = FALSE;
2663  } else {
2665  }
2666 
2667  break;
2668 
2670 
2671  //
2672  // An invalid request was attempted.
2673  //
2674 
2676  retry = FALSE;
2677  break;
2678 
2681 
2682  //
2683  // Update the error count for the device.
2684  //
2685 
2686  deviceExtension->ErrorCount++;
2687 
2688  //
2689  // Fall through to below.
2690  //
2691 
2692  case SRB_STATUS_BUS_RESET:
2694  break;
2695 
2696  case SRB_STATUS_ERROR:
2697 
2699  if (Srb->ScsiStatus == 0) {
2700 
2701  //
2702  // This is some strange return code. Update the error
2703  // count for the device.
2704  //
2705 
2706  deviceExtension->ErrorCount++;
2707 
2708  } if (Srb->ScsiStatus == SCSISTAT_BUSY) {
2709 
2711 
2712  } if (Srb->ScsiStatus == SCSISTAT_RESERVATION_CONFLICT) {
2713 
2715  retry = FALSE;
2716 
2717  }
2718 
2719  break;
2720 
2721  default:
2722  logError = TRUE;
2723  logStatus = 0;//IO_ERR_CONTROLLER_ERROR;
2724  uniqueId = 259;
2726  break;
2727 
2728  }
2729 
2730  //
2731  // If the error count has exceeded the error limit, then disable
2732  // any tagged queuing, multiple requests per lu queueing
2733  // and synchronous data transfers.
2734  //
2735 
2736  if (deviceExtension->ErrorCount == 4) {
2737 
2738  //
2739  // Clearing the no queue freeze flag prevents the port driver
2740  // from sending multiple requests per logical unit.
2741  //
2742 
2743  deviceExtension->SrbFlags &= ~(SRB_FLAGS_QUEUE_ACTION_ENABLE |
2745 
2746  deviceExtension->SrbFlags |= SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
2747  DebugPrint((1, "ScsiClassInterpretSenseInfo: Too many errors disabling tagged queuing and synchronous data tranfers.\n"));
2748 
2749  } else if (deviceExtension->ErrorCount == 8) {
2750 
2751  //
2752  // If a second threshold is reached, disable disconnects.
2753  //
2754 
2755  deviceExtension->SrbFlags |= SRB_FLAGS_DISABLE_DISCONNECT;
2756  DebugPrint((1, "ScsiClassInterpretSenseInfo: Too many errors disabling disconnects.\n"));
2757  }
2758  }
2759 
2760  //
2761  // If there is a class specific error handler call it.
2762  //
2763 
2764  if (deviceExtension->ClassError != NULL) {
2765 
2766  deviceExtension->ClassError(DeviceObject,
2767  Srb,
2768  Status,
2769  &retry);
2770  }
2771 
2772  //
2773  // Log an error if necessary.
2774  //
2775 
2776  if (logError) {
2777 
2779  DeviceObject,
2780  sizeof(IO_ERROR_LOG_PACKET) + 5 * sizeof(ULONG));
2781 
2782  if (errorLogEntry == NULL) {
2783 
2784  //
2785  // Return if no packet could be allocated.
2786  //
2787 
2788  return retry;
2789 
2790  }
2791 
2792  if (retry && RetryCount < MAXIMUM_RETRIES) {
2793  errorLogEntry->FinalStatus = STATUS_SUCCESS;
2794  } else {
2795  errorLogEntry->FinalStatus = *Status;
2796  }
2797 
2798  //
2799  // Calculate the device offset if there is a geometry.
2800  //
2801 
2802  if (deviceExtension->DiskGeometry != NULL) {
2803 
2804  errorLogEntry->DeviceOffset.QuadPart = (LONGLONG) badSector;
2805  errorLogEntry->DeviceOffset = RtlExtendedIntegerMultiply(
2806  errorLogEntry->DeviceOffset,
2807  deviceExtension->DiskGeometry->Geometry.BytesPerSector);
2808  }
2809 
2810  errorLogEntry->ErrorCode = logStatus;
2811  errorLogEntry->SequenceNumber = 0;
2812  errorLogEntry->MajorFunctionCode = MajorFunctionCode;
2813  errorLogEntry->IoControlCode = IoDeviceCode;
2814  errorLogEntry->RetryCount = (UCHAR) RetryCount;
2815  errorLogEntry->UniqueErrorValue = uniqueId;
2816  errorLogEntry->DumpDataSize = 6 * sizeof(ULONG);
2817  errorLogEntry->DumpData[0] = Srb->PathId;
2818  errorLogEntry->DumpData[1] = Srb->TargetId;
2819  errorLogEntry->DumpData[2] = Srb->Lun;
2820  errorLogEntry->DumpData[3] = 0;
2821  errorLogEntry->DumpData[4] = Srb->SrbStatus << 8 | Srb->ScsiStatus;
2822 
2823  if (senseBuffer != NULL) {
2824  errorLogEntry->DumpData[5] = senseBuffer->SenseKey << 16 |
2825  senseBuffer->AdditionalSenseCode << 8 |
2826  senseBuffer->AdditionalSenseCodeQualifier;
2827 
2828  }
2829 
2830  //
2831  // Write the error log packet.
2832  //
2833 
2834  IoWriteErrorLogEntry(errorLogEntry);
2835  }
2836 
2837  return retry;
2838 
2839 } // end ScsiClassInterpretSenseInfo()
2840 
2841 
2842 VOID
2843 NTAPI
2846  PIRP Irp,
2848  BOOLEAN Associated
2849  )
2850 
2851 /*++
2852 
2853 Routine Description:
2854 
2855  This routine reinitializes the necessary fields, and sends the request
2856  to the port driver.
2857 
2858 Arguments:
2859 
2860  DeviceObject - Supplies the device object associated with this request.
2861 
2862  Irp - Supplies the request to be retried.
2863 
2864  Srb - Supplies a Pointer to the SCSI request block to be retied.
2865 
2866  Associated - Indicates this is an associated Irp created by split request.
2867 
2868 Return Value:
2869 
2870  None
2871 
2872 --*/
2873 
2874 {
2875  PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
2878  ULONG transferByteCount;
2879 
2880  ASSERT(*(PULONG)deviceExtension != '2slc');
2881 
2882  //
2883  // Determine the transfer count of the request. If this is a read or a
2884  // write then the transfer count is in the Irp stack. Otherwise assume
2885  // the MDL contains the correct length. If there is no MDL then the
2886  // transfer length must be zero.
2887  //
2888 
2889  if (currentIrpStack->MajorFunction == IRP_MJ_READ ||
2890  currentIrpStack->MajorFunction == IRP_MJ_WRITE) {
2891 
2892  transferByteCount = currentIrpStack->Parameters.Read.Length;
2893 
2894  } else if (Irp->MdlAddress != NULL) {
2895 
2896  //
2897  // Note this assumes that only read and write requests are spilt and
2898  // other request do not need to be. If the data buffer address in
2899  // the MDL and the SRB don't match then transfer length is most
2900  // likely incorrect.
2901  //
2902 
2903  ASSERT(Srb->DataBuffer == MmGetMdlVirtualAddress(Irp->MdlAddress));
2904  transferByteCount = Irp->MdlAddress->ByteCount;
2905 
2906  } else {
2907 
2908  transferByteCount = 0;
2909  }
2910 
2911  //
2912  // Reset byte count of transfer in SRB Extension.
2913  //
2914 
2915  Srb->DataTransferLength = transferByteCount;
2916 
2917  //
2918  // Zero SRB statuses.
2919  //
2920 
2921  Srb->SrbStatus = Srb->ScsiStatus = 0;
2922 
2923  //
2924  // Set the no disconnect flag, disable synchronous data transfers and
2925  // disable tagged queuing. This fixes some errors.
2926  //
2927 
2928  Srb->SrbFlags |= SRB_FLAGS_DISABLE_DISCONNECT |
2930 
2931  Srb->SrbFlags &= ~SRB_FLAGS_QUEUE_ACTION_ENABLE;
2932  Srb->QueueTag = SP_UNTAGGED;
2933 
2934  //
2935  // Set up major SCSI function.
2936  //
2937 
2938  nextIrpStack->MajorFunction = IRP_MJ_SCSI;
2939 
2940  //
2941  // Save SRB address in next stack for port driver.
2942  //
2943 
2944  nextIrpStack->Parameters.Scsi.Srb = Srb;
2945 
2946  //
2947  // Set up IoCompletion routine address.
2948  //
2949 
2950  if (Associated) {
2951 
2953 
2954  } else {
2955 
2957  }
2958 
2959  //
2960  // Pass the request to the port driver.
2961  //
2962 
2963  (VOID)IoCallDriver(deviceExtension->PortDeviceObject, Irp);
2964 
2965 } // end RetryRequest()
2966 
2967 VOID
2968 NTAPI
2971  PIRP Irp
2972  )
2973 
2974 /*++
2975 
2976 Routine Description:
2977 
2978  This routine allocates and builds an Srb for a read or write request.
2979  The block address and length are supplied by the Irp. The retry count
2980  is stored in the current stack for use by ScsiClassIoComplete which
2981  processes these requests when they complete. The Irp is ready to be
2982  passed to the port driver when this routine returns.
2983 
2984 Arguments:
2985 
2986  DeviceObject - Supplies the device object associated with this request.
2987 
2988  Irp - Supplies the request to be retried.
2989 
2990 Note:
2991 
2992  If the IRP is for a disk transfer, the byteoffset field
2993  will already have been adjusted to make it relative to
2994  the beginning of the disk.
2995 
2996 
2997 Return Value:
2998 
2999  None.
3000 
3001 --*/
3002 
3003 {
3004  PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
3007  LARGE_INTEGER startingOffset = currentIrpStack->Parameters.Read.ByteOffset;
3008  PSCSI_REQUEST_BLOCK srb;
3009  PCDB cdb;
3010  ULONG logicalBlockAddress;
3011  USHORT transferBlocks;
3012 
3013  ASSERT(*(PULONG)deviceExtension != '2slc');
3014 
3015  //
3016  // Calculate relative sector address.
3017  //
3018 
3019  logicalBlockAddress = (ULONG)(Int64ShrlMod32(startingOffset.QuadPart, deviceExtension->SectorShift));
3020 
3021  //
3022  // Allocate an Srb.
3023  //
3024 
3025  srb = ExAllocateFromNPagedLookasideList(&deviceExtension->SrbLookasideListHead);
3026 
3027  srb->SrbFlags = 0;
3028 
3029  //
3030  // Write length to SRB.
3031  //
3032 
3034 
3035  //
3036  // Set up IRP Address.
3037  //
3038 
3039  srb->OriginalRequest = Irp;
3040 
3041  //
3042  // Set up target ID and logical unit number.
3043  //
3044 
3045  srb->PathId = deviceExtension->PathId;
3046  srb->TargetId = deviceExtension->TargetId;
3047  srb->Lun = deviceExtension->Lun;
3049  srb->DataBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress);
3050 
3051  //
3052  // Save byte count of transfer in SRB Extension.
3053  //
3054 
3055  srb->DataTransferLength = currentIrpStack->Parameters.Read.Length;
3056 
3057  //
3058  // Initialize the queue actions field.
3059  //
3060 
3062 
3063  //
3064  // Queue sort key is Relative Block Address.
3065  //
3066 
3067  srb->QueueSortKey = logicalBlockAddress;
3068 
3069  //
3070  // Indicate auto request sense by specifying buffer and size.
3071  //
3072 
3073  srb->SenseInfoBuffer = deviceExtension->SenseData;
3075 
3076  //
3077  // Set timeout value of one unit per 64k bytes of data.
3078  //
3079 
3080  srb->TimeOutValue = ((srb->DataTransferLength + 0xFFFF) >> 16) *
3081  deviceExtension->TimeOutValue;
3082 
3083  //
3084  // Zero statuses.
3085  //
3086 
3087  srb->SrbStatus = srb->ScsiStatus = 0;
3088  srb->NextSrb = 0;
3089 
3090  //
3091  // Indicate that 10-byte CDB's will be used.
3092  //
3093 
3094  srb->CdbLength = 10;
3095 
3096  //
3097  // Fill in CDB fields.
3098  //
3099 
3100  cdb = (PCDB)srb->Cdb;
3101 
3102  //
3103  // Zero 12 bytes for Atapi Packets
3104  //
3105 
3107 
3108  cdb->CDB10.LogicalUnitNumber = deviceExtension->Lun;
3109  transferBlocks = (USHORT)(currentIrpStack->Parameters.Read.Length >> deviceExtension->SectorShift);
3110 
3111  //
3112  // Move little endian values into CDB in big endian format.
3113  //
3114 
3115  cdb->CDB10.LogicalBlockByte0 = ((PFOUR_BYTE)&logicalBlockAddress)->Byte3;
3116  cdb->CDB10.LogicalBlockByte1 = ((PFOUR_BYTE)&logicalBlockAddress)->Byte2;
3117  cdb->CDB10.LogicalBlockByte2 = ((PFOUR_BYTE)&logicalBlockAddress)->Byte1;
3118  cdb->CDB10.LogicalBlockByte3 = ((PFOUR_BYTE)&logicalBlockAddress)->Byte0;
3119 
3120  cdb->CDB10.TransferBlocksMsb = ((PFOUR_BYTE)&transferBlocks)->Byte1;
3121  cdb->CDB10.TransferBlocksLsb = ((PFOUR_BYTE)&transferBlocks)->Byte0;
3122 
3123  //
3124  // Set transfer direction flag and Cdb command.
3125  //
3126 
3127  if (currentIrpStack->MajorFunction == IRP_MJ_READ) {
3128 
3129  DebugPrint((3, "ScsiClassBuildRequest: Read Command\n"));
3130 
3131  srb->SrbFlags |= SRB_FLAGS_DATA_IN;
3132  cdb->CDB10.OperationCode = SCSIOP_READ;
3133 
3134  } else {
3135 
3136  DebugPrint((3, "ScsiClassBuildRequest: Write Command\n"));
3137 
3138  srb->SrbFlags |= SRB_FLAGS_DATA_OUT;
3139  cdb->CDB10.OperationCode = SCSIOP_WRITE;
3140  }
3141 
3142  //
3143  // If this is not a write-through request, then allow caching.
3144  //
3145 
3146  if (!(currentIrpStack->Flags & SL_WRITE_THROUGH)) {
3147 
3149 
3150  } else {
3151 
3152  //
3153  // If write caching is enable then force media access in the
3154  // cdb.
3155  //
3156 
3157  if (deviceExtension->DeviceFlags & DEV_WRITE_CACHE) {
3158  cdb->CDB10.ForceUnitAccess = TRUE;
3159  }
3160  }
3161 
3162  //
3163  // Or in the default flags from the device object.
3164  //
3165 
3166  srb->SrbFlags |= deviceExtension->SrbFlags;
3167 
3168  //
3169  // Set up major SCSI function.
3170  //
3171 
3172  nextIrpStack->MajorFunction = IRP_MJ_SCSI;
3173 
3174  //
3175  // Save SRB address in next stack for port driver.
3176  //
3177 
3178  nextIrpStack->Parameters.Scsi.Srb = srb;
3179 
3180  //
3181  // Save retry count in current IRP stack.
3182  //
3183 
3184  currentIrpStack->Parameters.Others.Argument4 = (PVOID)MAXIMUM_RETRIES;
3185 
3186  //
3187  // Set up IoCompletion routine address.
3188  //
3189 
3191 
3192  return;
3193 
3194 } // end ScsiClassBuildRequest()
3195 
3196 ULONG
3197 NTAPI
3200  IN PCHAR ModeSenseBuffer,
3201  IN ULONG Length,
3202  IN UCHAR PageMode
3203  )
3204 
3205 /*++
3206 
3207 Routine Description:
3208 
3209  This routine sends a mode sense command to a target ID and returns
3210  when it is complete.
3211 
3212 Arguments:
3213 
3214  DeviceObject - Supplies the device object associated with this request.
3215 
3216  ModeSenseBuffer - Supplies a buffer to store the sense data.
3217 
3218  Length - Supplies the length in bytes of the mode sense buffer.
3219 
3220  PageMode - Supplies the page or pages of mode sense data to be retrieved.
3221 
3222 Return Value:
3223 
3224  Length of the transferred data is returned.
3225 
3226 --*/
3227 {
3228  PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
3229  PCDB cdb;
3230  SCSI_REQUEST_BLOCK srb;
3231  ULONG retries = 1;
3232  NTSTATUS status;
3233 
3234  ASSERT(*(PULONG)deviceExtension != '2slc');
3235 
3236  RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK));
3237 
3238  //
3239  // Build the MODE SENSE CDB.
3240  //
3241 
3242  srb.CdbLength = 6;
3243  cdb = (PCDB)srb.Cdb;
3244 
3245  //
3246  // Set timeout value from device extension.
3247  //
3248 
3249  srb.TimeOutValue = deviceExtension->TimeOutValue;
3250 
3251  cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
3252  cdb->MODE_SENSE.PageCode = PageMode;
3253  cdb->MODE_SENSE.AllocationLength = (UCHAR)Length;
3254 
3255 Retry:
3256 
3258  &srb,
3259  ModeSenseBuffer,
3260  Length,
3261  FALSE);
3262 
3263 
3264  if (status == STATUS_VERIFY_REQUIRED) {
3265 
3266  //
3267  // Routine ScsiClassSendSrbSynchronous does not retry requests returned with
3268  // this status. MODE SENSE commands should be retried anyway.
3269  //
3270 
3271  if (retries--) {
3272 
3273  //
3274  // Retry request.
3275  //
3276 
3277  goto Retry;
3278  }
3279 
3280  } else if (SRB_STATUS(srb.SrbStatus) == SRB_STATUS_DATA_OVERRUN) {
3282  }
3283 
3284  if (NT_SUCCESS(status)) {
3285  return(srb.DataTransferLength);
3286  } else {
3287  return(0);
3288  }
3289 
3290 } // end ScsiClassModeSense()
3291 
3292 
3293 PVOID
3294 NTAPI
3296  IN PCHAR ModeSenseBuffer,
3297  IN ULONG Length,
3298  IN UCHAR PageMode,
3299  IN BOOLEAN Use6Byte
3300  )
3301 
3302 /*++
3303 
3304 Routine Description:
3305 
3306  This routine scans through the mode sense data and finds the requested
3307  mode sense page code.
3308 
3309 Arguments:
3310  ModeSenseBuffer - Supplies a pointer to the mode sense data.
3311 
3312  Length - Indicates the length of valid data.
3313 
3314  PageMode - Supplies the page mode to be searched for.
3315 
3316  Use6Byte - Indicates whether 6 or 10 byte mode sense was used.
3317 
3318 Return Value:
3319 
3320  A pointer to the the requested mode page. If the mode page was not found
3321  then NULL is return.
3322 
3323 --*/
3324 {
3325  PUCHAR limit;
3326  ULONG parameterHeaderLength;
3327 
3328  limit = (PUCHAR)ModeSenseBuffer + Length;
3329  parameterHeaderLength = (Use6Byte) ? sizeof(MODE_PARAMETER_HEADER) : sizeof(MODE_PARAMETER_HEADER10);
3330 
3331 
3332  //
3333  // Skip the mode select header and block descriptors.
3334  //
3335 
3336  if (Length < parameterHeaderLength) {
3337  return(NULL);
3338  }
3339 
3340 
3341 
3342  ModeSenseBuffer += parameterHeaderLength + ((Use6Byte) ? ((PMODE_PARAMETER_HEADER) ModeSenseBuffer)->BlockDescriptorLength :
3343  ((PMODE_PARAMETER_HEADER10) ModeSenseBuffer)->BlockDescriptorLength[1]);
3344 
3345  //
3346  // ModeSenseBuffer now points at pages. Walk the pages looking for the
3347  // requested page until the limit is reached.
3348  //
3349 
3350 
3351  while ((PUCHAR)ModeSenseBuffer < limit) {
3352 
3353  if (((PMODE_DISCONNECT_PAGE) ModeSenseBuffer)->PageCode == PageMode) {
3354  return(ModeSenseBuffer);
3355  }
3356 
3357  //
3358  // Advance to the next page.
3359  //
3360 
3361  ModeSenseBuffer += ((PMODE_DISCONNECT_PAGE) ModeSenseBuffer)->PageLength + 2;
3362  }
3363 
3364  return(NULL);
3365 }
3366 
3367 NTSTATUS
3368 NTAPI
3372  PIRP Irp,
3373  PVOID BufferAddress,
3375  BOOLEAN WriteToDevice
3376  )
3377 /*++
3378 
3379 Routine Description:
3380 
3381  This routine takes a partially built Srb and an Irp and sends it down to
3382  the port driver.
3383 
3384 Arguments:
3385  DeviceObject - Supplies the device object for the original request.
3386 
3387  Srb - Supplies a partially built ScsiRequestBlock. In particular, the
3388  CDB and the SRB timeout value must be filled in. The SRB must not be
3389  allocated from zone.
3390 
3391  Irp - Supplies the requesting Irp.
3392 
3393  BufferAddress - Supplies a pointer to the buffer to be transfered.
3394 
3395  BufferLength - Supplies the length of data transfer.
3396 
3397  WriteToDevice - Indicates the data transfer will be from system memory to
3398  device.
3399 
3400 Return Value:
3401 
3402  Returns STATUS_INSUFFICIENT_RESOURCES or the status of IoCallDriver.
3403 
3404 --*/
3405 {
3406 
3407  PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
3408  PIO_STACK_LOCATION irpStack;
3409 
3410  PAGED_CODE();
3411 
3412  ASSERT(*(PULONG)deviceExtension != '2slc');
3413 
3414  //
3415  // Write length to SRB.
3416  //
3417 
3418  Srb->Length = SCSI_REQUEST_BLOCK_SIZE;
3419 
3420  //
3421  // Set SCSI bus address.
3422  //
3423 
3424  Srb->PathId = deviceExtension->PathId;
3425  Srb->TargetId = deviceExtension->TargetId;
3426  Srb->Lun = deviceExtension->Lun;
3427 
3428  Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
3429 
3430  //
3431  // This is a violation of the SCSI spec but it is required for
3432  // some targets.
3433  //
3434 
3435  Srb->Cdb[1] |= deviceExtension->Lun << 5;
3436 
3437  //
3438  // Indicate auto request sense by specifying buffer and size.
3439  //
3440 
3441  Srb->SenseInfoBuffer = deviceExtension->SenseData;
3442  Srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE;
3443  Srb->DataBuffer = BufferAddress;
3444 
3445  if (BufferAddress != NULL) {
3446 
3447  //
3448  // Build Mdl if necessary.
3449  //
3450 
3451  if (Irp->MdlAddress == NULL) {
3452 
3453  if (IoAllocateMdl(BufferAddress,
3454  BufferLength,
3455  FALSE,
3456  FALSE,
3457  Irp) == NULL) {
3458 
3460  }
3461 
3462  MmBuildMdlForNonPagedPool(Irp->MdlAddress);
3463 
3464  } else {
3465 
3466  //
3467  // Make sure the buffer requested matches the MDL.
3468  //
3469 
3470  ASSERT(BufferAddress == MmGetMdlVirtualAddress(Irp->MdlAddress));
3471  }
3472 
3473  //
3474  // Set read flag.
3475  //
3476 
3477  Srb->SrbFlags = WriteToDevice ? SRB_FLAGS_DATA_OUT : SRB_FLAGS_DATA_IN;
3478 
3479  } else {
3480 
3481  //
3482  // Clear flags.
3483  //
3484 
3485  Srb->SrbFlags = SRB_FLAGS_NO_DATA_TRANSFER;
3486  }
3487 
3488  //
3489  // Disable synchronous transfer for these requests.
3490  //
3491 
3493 
3494  //
3495  // Set the transfer length.
3496  //
3497 
3498  Srb->DataTransferLength = BufferLength;
3499 
3500  //
3501  // Zero out status.
3502  //
3503 
3504  Srb->ScsiStatus = Srb->SrbStatus = 0;
3505 
3506  Srb->NextSrb = 0;
3507 
3508  //
3509  // Save a few parameters in the current stack location.
3510  //
3511 
3512  irpStack = IoGetCurrentIrpStackLocation(Irp);
3513 
3514  //
3515  // Save retry count in current Irp stack.
3516  //
3517 
3518  irpStack->Parameters.Others.Argument4 = (PVOID)MAXIMUM_RETRIES;
3519 
3520  //
3521  // Set up IoCompletion routine address.
3522  //
3523 
3525 
3526  //
3527  // Get next stack location and
3528  // set major function code.
3529  //
3530 
3531  irpStack = IoGetNextIrpStackLocation(Irp);
3532 
3533  irpStack->MajorFunction = IRP_MJ_SCSI;
3534 
3535  //
3536  // Save SRB address in next stack for port driver.
3537  //
3538 
3539  irpStack->Parameters.Scsi.Srb = Srb;
3540 
3541  //
3542  // Set up Irp Address.
3543  //
3544 
3545  Srb->OriginalRequest = Irp;
3546 
3547  //
3548  // Call the port driver to process the request.
3549  //
3550 
3551  return(IoCallDriver(deviceExtension->PortDeviceObject, Irp));
3552 
3553 }
3554 
3555 
3556 NTSTATUS
3557 NTAPI
3560  PIRP Irp
3561  )
3562 
3563 /*++
3564 
3565 Routine Description:
3566 
3567  The routine is the common class driver device control dispatch entry point.
3568  This routine is invokes the device-specific drivers DeviceControl routine,
3569  (which may call the Class driver's common DeviceControl routine).
3570 
3571 Arguments:
3572 
3573  DeviceObject - Supplies a pointer to the device object for this request.
3574 
3575  Irp - Supplies the Irp making the request.
3576 
3577 Return Value:
3578 
3579  Returns the status returned from the device-specific driver.
3580 
3581 --*/
3582 
3583 {
3584 
3585  PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
3586 
3587  ASSERT(*(PULONG)deviceExtension != '2slc');
3588 
3589  //
3590  // Call the class specific driver DeviceControl routine.
3591  // If it doesn't handle it, it will call back into ScsiClassDeviceControl.
3592  //
3593 
3594  ASSERT(deviceExtension->ClassDeviceControl);
3595 
3596  return deviceExtension->ClassDeviceControl(DeviceObject,Irp);
3597 }
3598 
3599 
3600 NTSTATUS
3601 NTAPI
3604  PIRP Irp
3605  )
3606 /*++
3607 
3608 Routine Description:
3609 
3610  The routine is the common class driver device control dispatch function.
3611  This routine is called by a class driver when it get an unrecognized
3612  device control request. This routine will perform the correct action for
3613  common requests such as lock media. If the device request is unknown it
3614  passed down to the next level.
3615 
3616 Arguments:
3617 
3618  DeviceObject - Supplies a pointer to the device object for this request.
3619 
3620  Irp - Supplies the Irp making the request.
3621 
3622 Return Value:
3623 
3624  Returns back a STATUS_PENDING or a completion status.
3625 
3626 --*/
3627 
3628 {
3630  PIO_STACK_LOCATION nextStack;
3631  PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
3632  PSCSI_REQUEST_BLOCK srb;
3633  PCDB cdb;
3634  NTSTATUS status;
3635  ULONG modifiedIoControlCode;
3636 
3637  ASSERT(*(PULONG)deviceExtension != '2slc');
3638 
3639  if (irpStack->Parameters.DeviceIoControl.IoControlCode ==
3641 
3642  Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
3645  goto SetStatusAndReturn;
3646  }
3647 
3648  //
3649  // If this is a pass through I/O control, set the minor function code
3650  // and device address and pass it to the port driver.
3651  //
3652 
3653  if (irpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SCSI_PASS_THROUGH
3654  || irpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SCSI_PASS_THROUGH_DIRECT) {
3655 
3656  PSCSI_PASS_THROUGH scsiPass;
3657 
3658  nextStack = IoGetNextIrpStackLocation(Irp);
3659 
3660  //
3661  // Validate the user buffer.
3662  //
3663 
3664  if (irpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(SCSI_PASS_THROUGH)){
3665 
3666  Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
3669  goto SetStatusAndReturn;
3670  }
3671 
3672  //
3673  // Force the SCSI address to the correct value.
3674  //
3675 
3676  scsiPass = Irp->AssociatedIrp.SystemBuffer;
3677  scsiPass->PathId = deviceExtension->PathId;
3678  scsiPass->TargetId = deviceExtension->TargetId;
3679  scsiPass->Lun = deviceExtension->Lun;
3680 
3681  //
3682  // NOTICE: The SCSI-II specification indicates that this field
3683  // should be zero; however, some target controllers ignore the logical
3684  // unit number in the IDENTIFY message and only look at the logical
3685  // unit number field in the CDB.
3686  //
3687 
3688  scsiPass->Cdb[1] |= deviceExtension->Lun << 5;
3689 
3690  nextStack->Parameters = irpStack->Parameters;
3691  nextStack->MajorFunction = irpStack->MajorFunction;
3692  nextStack->MinorFunction = IRP_MN_SCSI_CLASS;
3693 
3694  status = IoCallDriver(deviceExtension->PortDeviceObject, Irp);
3695  goto SetStatusAndReturn;
3696  }
3697 
3698  if (irpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SCSI_GET_ADDRESS) {
3699 
3700  PSCSI_ADDRESS scsiAddress = Irp->AssociatedIrp.SystemBuffer;
3701 
3702  if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
3703  sizeof(SCSI_ADDRESS)) {
3704 
3705  //
3706  // Indicate unsuccessful status and no data transferred.
3707  //
3708 
3709  Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
3710  Irp->IoStatus.Information = 0;
3713  goto SetStatusAndReturn;
3714 
3715  }
3716 
3717  scsiAddress->Length = sizeof(SCSI_ADDRESS);
3718  scsiAddress->PortNumber = deviceExtension->PortNumber;
3719  scsiAddress->PathId = deviceExtension->PathId;
3720  scsiAddress->TargetId = deviceExtension->TargetId;
3721  scsiAddress->Lun = deviceExtension->Lun;
3722  Irp->IoStatus.Information = sizeof(SCSI_ADDRESS);
3723  Irp->IoStatus.Status = STATUS_SUCCESS;
3726  goto SetStatusAndReturn;
3727  }
3728 
3729  if (irpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME) {
3730 
3731  UNIMPLEMENTED;
3732  Irp->IoStatus.Information = 0;
3733  Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
3736  goto SetStatusAndReturn;
3737  }
3738 
3739  if (irpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_MOUNTDEV_QUERY_UNIQUE_ID) {
3740 
3741  //
3742  // FIXME
3743  // This is a HACK. We don't have unique ID.
3744  // We'll just return device name as unique ID.
3745  // It's unique but may not survive to a reboot,
3746  // which is not matching the requirements for
3747  // a MountMgr unique ID.
3748  //
3749 
3750  PMOUNTDEV_UNIQUE_ID uniqueId = Irp->AssociatedIrp.SystemBuffer;
3751 
3752  //
3753  // Check output buffer is big enough.
3754  //
3755 
3756  if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(MOUNTDEV_UNIQUE_ID)) {
3757 
3758  Irp->IoStatus.Information = 0;
3759  Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
3762  goto SetStatusAndReturn;
3763  }
3764 
3765  //
3766  // Set size we'll return so that caller can allocate big enough buffer.
3767  //
3768 
3769  RtlZeroMemory(uniqueId, sizeof(MOUNTDEV_UNIQUE_ID));
3770  uniqueId->UniqueIdLength = deviceExtension->DeviceName.Length;
3771 
3772  //
3773  // Check buffer is big enough to contain device name.
3774  //
3775 
3776  if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < FIELD_OFFSET(MOUNTDEV_UNIQUE_ID, UniqueId) + uniqueId->UniqueIdLength) {
3777 
3778  Irp->IoStatus.Information = sizeof(MOUNTDEV_UNIQUE_ID);
3779  Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
3782  goto SetStatusAndReturn;
3783  }
3784 
3785  //
3786  // Copy device name.
3787  //
3788 
3789  RtlCopyMemory(uniqueId->UniqueId, deviceExtension->DeviceName.Buffer,
3790  uniqueId->UniqueIdLength);
3792 
3793  //
3794  // And return to the caller.
3795  //
3796 
3797  Irp->IoStatus.Status = STATUS_SUCCESS;
3798  Irp->IoStatus.Information = FIELD_OFFSET(MOUNTDEV_UNIQUE_ID, UniqueId) + uniqueId->UniqueIdLength;
3800  goto SetStatusAndReturn;
3801  }
3802 
3803  if (irpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_MOUNTDEV_QUERY_DEVICE_NAME) {
3804 
3805  PMOUNTDEV_NAME name = Irp->AssociatedIrp.SystemBuffer;
3806 
3807  if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(MOUNTDEV_NAME)) {
3808 
3809  Irp->IoStatus.Information = 0;
3810  Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
3813  goto SetStatusAndReturn;
3814  }
3815 
3816  RtlZeroMemory(name, sizeof(MOUNTDEV_NAME));
3817  name->NameLength = deviceExtension->DeviceName.Length;
3818 
3819  if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < FIELD_OFFSET(MOUNTDEV_NAME, Name) + name->NameLength) {
3820 
3821  Irp->IoStatus.Information = sizeof(MOUNTDEV_NAME);
3822  Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
3825  goto SetStatusAndReturn;
3826  }
3827 
3828  RtlCopyMemory(name->Name, deviceExtension->DeviceName.Buffer,
3829  name->NameLength);
3831  Irp->IoStatus.Status = STATUS_SUCCESS;
3832  Irp->IoStatus.Information = FIELD_OFFSET(MOUNTDEV_NAME, Name) + name->NameLength;
3834  goto SetStatusAndReturn;
3835  }
3836 
3838 
3839  if (srb == NULL) {
3840 
3841  Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
3844  goto SetStatusAndReturn;
3845  }
3846 
3847  //
3848  // Write zeros to Srb.
3849  //
3850 
3852 
3853  cdb = (PCDB)srb->Cdb;
3854 
3855  //
3856  // Change the device type to disk for the switch statement.
3857  //
3858 
3859  modifiedIoControlCode = (irpStack->Parameters.DeviceIoControl.IoControlCode
3860  & ~0xffff0000) | (IOCTL_DISK_BASE << 16);
3861 
3862  switch (modifiedIoControlCode) {
3863 
3864  case IOCTL_DISK_CHECK_VERIFY: {
3865 
3866  PIRP irp2 = NULL;
3867  PIO_STACK_LOCATION newStack;
3868 
3869  DebugPrint((1,"ScsiDeviceIoControl: Check verify\n"));
3870 
3871  //
3872  // If a buffer for a media change count was provided, make sure it's
3873  // big enough to hold the result
3874  //
3875 
3876  if(irpStack->Parameters.DeviceIoControl.OutputBufferLength) {
3877 
3878  //
3879  // If the buffer is too small to hold the media change count
3880  // then return an error to the caller
3881  //
3882 
3883  if(irpStack->Parameters.DeviceIoControl.OutputBufferLength <
3884  sizeof(ULONG)) {
3885 
3886  DebugPrint((3,"ScsiDeviceIoControl: media count "
3887  "buffer too small\n"));
3888 
3889  Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
3890  Irp->IoStatus.Information = 0;
3891  ExFreePool(srb);
3894  goto SetStatusAndReturn;
3895 
3896  }
3897 
3898  //
3899  // The caller has provided a valid buffer. Allocate an additional
3900  // irp and stick the CheckVerify completion routine on it. We will
3901  // then send this down to the port driver instead of the irp the
3902  // caller sent in
3903  //
3904 
3905  DebugPrint((2,"ScsiDeviceIoControl: Check verify wants "
3906  "media count\n"));
3907 
3908  //
3909  // Allocate a new irp to send the TestUnitReady to the port driver
3910  //
3911 
3912  irp2 = IoAllocateIrp((CCHAR) (DeviceObject->StackSize + 3), FALSE);
3913 
3914  if(irp2 == NULL) {
3915  Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
3916  Irp->IoStatus.Information = 0;
3917  ExFreePool(srb);
3920  goto SetStatusAndReturn;
3921  }
3922 
3923  irp2->Tail.Overlay.Thread = Irp->Tail.Overlay.Thread;
3925 
3926  //
3927  // Set the top stack location and shove the master Irp into the
3928  // top location
3929  //
3930 
3931  newStack = IoGetCurrentIrpStackLocation(irp2);
3932  newStack->Parameters.Others.Argument1 = Irp;
3933  newStack->DeviceObject = DeviceObject;
3934 
3935  //
3936  // Stick the check verify completion routine onto the stack
3937  // and prepare the irp for the port driver
3938  //
3939 
3942  NULL,
3943  TRUE,
3944  TRUE,
3945  TRUE);
3946 
3948  newStack = IoGetCurrentIrpStackLocation(irp2);
3949  newStack->DeviceObject = DeviceObject;
3950 
3951  //
3952  // Mark the master irp as pending - whether the lower level
3953  // driver completes it immediately or not this should allow it
3954  // to go all the way back up.
3955  //
3956 
3958 
3959  Irp = irp2;
3960 
3961  }
3962 
3963  //
3964  // Test Unit Ready
3965  //
3966 
3967  srb->CdbLength = 6;
3968  cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY;
3969 
3970  //
3971  // Set timeout value.
3972  //
3973 
3974  srb->TimeOutValue = deviceExtension->TimeOutValue;
3975 
3976  //
3977  // Since this routine will always hand the request to the
3978  // port driver if there isn't a data transfer to be done
3979  // we don't have to worry about completing the request here
3980  // on an error
3981  //
3982 
3984  srb,
3985  Irp,
3986  NULL,
3987  0,
3988  FALSE);
3989 
3990  break;
3991  }
3992 
3993  case IOCTL_DISK_MEDIA_REMOVAL: {
3994 
3995  PPREVENT_MEDIA_REMOVAL MediaRemoval = Irp->AssociatedIrp.SystemBuffer;
3996 
3997  //
3998  // Prevent/Allow media removal.
3999  //
4000 
4001  DebugPrint((3,"DiskIoControl: Prevent/Allow media removal\n"));
4002 
4003  if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
4004  sizeof(PREVENT_MEDIA_REMOVAL)) {
4005 
4006  //
4007  // Indicate unsuccessful status and no data transferred.
4008  //
4009 
4010  Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
4011  Irp->IoStatus.Information = 0;
4012  ExFreePool(srb);
4015  goto SetStatusAndReturn;
4016  }
4017 
4018  //
4019  // Get physical device extension. This is where the
4020  // lock count is stored.
4021  //
4022 
4023  deviceExtension = deviceExtension->PhysicalDevice->DeviceExtension;
4024 
4025  //
4026  // If command succeeded then increment or decrement lock counter.
4027  //
4028 
4029  if (MediaRemoval->PreventMediaRemoval) {
4030 
4031  //
4032  // This is a lock command. Reissue the command in case bus or device
4033  // was reset and lock cleared.
4034  //
4035 
4036  InterlockedIncrement(&deviceExtension->LockCount);
4037 
4038  DebugPrint((1,
4039  "ScsiClassDeviceControl: Lock media, lock count %x on disk %x\n",
4040  deviceExtension->LockCount,
4041  deviceExtension->DeviceNumber));
4042 
4043  } else {
4044 
4045  //
4046  // This is an unlock command.
4047  //
4048 
4049  if (!deviceExtension->LockCount ||
4050  (InterlockedDecrement(&deviceExtension->LockCount) != 0)) {
4051 
4052  DebugPrint((1,
4053  "ScsiClassDeviceControl: Unlock media, lock count %x on disk %x\n",
4054  deviceExtension->LockCount,
4055  deviceExtension->DeviceNumber));
4056 
4057  //
4058  // Don't unlock because someone still wants it locked.
4059  //
4060 
4061  Irp->IoStatus.Status = STATUS_SUCCESS;
4062  ExFreePool(srb);
4065  goto SetStatusAndReturn;
4066  }
4067 
4068  DebugPrint((1,
4069  "ScsiClassDeviceControl: Unlock media, lock count %x on disk %x\n",
4070  deviceExtension->LockCount,
4071  deviceExtension->DeviceNumber));
4072  }
4073 
4074  srb->CdbLength = 6;
4075 
4076  cdb->MEDIA_REMOVAL.OperationCode = SCSIOP_MEDIUM_REMOVAL;
4077 
4078  //
4079  // TRUE - prevent media removal.
4080  // FALSE - allow media removal.
4081  //
4082 
4083  cdb->MEDIA_REMOVAL.Prevent = MediaRemoval->PreventMediaRemoval;
4084 
4085  //
4086  // Set timeout value.
4087  //
4088 
4089  srb->TimeOutValue = deviceExtension->TimeOutValue;
4091  srb,
4092  Irp,
4093  NULL,
4094  0,
4095  FALSE);
4096 
4097  //
4098  // Some devices will not support lock/unlock.
4099  // Pretend that it worked.
4100  //
4101 
4102  break;
4103  }
4104 
4105  case IOCTL_DISK_RESERVE: {
4106 
4107  //
4108  // Reserve logical unit.
4109  //
4110 
4111  srb->CdbLength = 6;
4112 
4113  cdb->CDB6GENERIC.OperationCode = SCSIOP_RESERVE_UNIT;
4114 
4115  //
4116  // Set timeout value.
4117  //
4118 
4119  srb->TimeOutValue = deviceExtension->TimeOutValue;
4120 
4122  srb,
4123  Irp,
4124  NULL,
4125  0,
4126  FALSE);
4127 
4128  break;
4129  }
4130 
4131  case IOCTL_DISK_RELEASE: {
4132 
4133  //
4134  // Release logical unit.
4135  //
4136 
4137  srb->CdbLength = 6;
4138 
4139  cdb->CDB6GENERIC.OperationCode = SCSIOP_RELEASE_UNIT;
4140 
4141  //
4142  // Set timeout value.
4143  //
4144 
4145  srb->TimeOutValue = deviceExtension->TimeOutValue;
4146 
4148  srb,
4149  Irp,
4150  NULL,
4151  0,
4152  FALSE);
4153 
4154  break;
4155  }
4156 
4157  case IOCTL_DISK_EJECT_MEDIA: {
4158 
4159  //
4160  // Eject media.
4161  //
4162 
4163  srb->CdbLength = 6;
4164 
4165  cdb->START_STOP.OperationCode = SCSIOP_START_STOP_UNIT;
4166  cdb->START_STOP.LoadEject = 1;
4167  cdb->START_STOP.Start = 0;
4168 
4169  //
4170  // Set timeout value.
4171  //
4172 
4173  srb->TimeOutValue = deviceExtension->TimeOutValue;
4175  srb,
4176  Irp,
4177  NULL,
4178  0,
4179  FALSE);
4180  break;
4181  }
4182 
4183  case IOCTL_DISK_LOAD_MEDIA: {
4184 
4185  //
4186  // Load media.
4187  //
4188 
4189  DebugPrint((3,"CdRomDeviceControl: Load media\n"));
4190 
4191  srb->CdbLength = 6;
4192 
4193  cdb->START_STOP.OperationCode = SCSIOP_START_STOP_UNIT;
4194  cdb->START_STOP.LoadEject = 1;
4195  cdb->START_STOP.Start = 1;
4196 
4197  //
4198  // Set timeout value.
4199  //
4200 
4201  srb->TimeOutValue = deviceExtension->TimeOutValue;
4203  srb,
4204  Irp,
4205  NULL,
4206  0,
4207  FALSE);
4208 
4209  break;
4210  }
4211 
4213 
4214  //
4215  // Search for devices that have been powered on since the last
4216  // device search or system initialization.
4217  //
4218 
4219  DebugPrint((3,"CdRomDeviceControl: Find devices\n"));
4220  status = DriverEntry(DeviceObject->DriverObject,
4221  NULL);
4222 
4223  Irp->IoStatus.Status = status;
4224  ExFreePool(srb);
4226 
4227  break;
4228  }
4229 
4230  default: {
4231 
4232  DebugPrint((3,"ScsiIoDeviceControl: Unsupported device IOCTL\n"));
4233 
4234  //
4235  // Pass the device control to the next driver.
4236  //
4237 
4238  ExFreePool(srb);
4239 
4240  //
4241  // Copy the Irp stack parameters to the next stack location.
4242  //
4243 
4244  nextStack = IoGetNextIrpStackLocation(Irp);
4245  nextStack->Parameters = irpStack->Parameters;
4246  nextStack->MajorFunction = irpStack->MajorFunction;
4247  nextStack->MinorFunction = irpStack->MinorFunction;
4248 
4249  status = IoCallDriver(deviceExtension->PortDeviceObject, Irp);
4250  break;
4251  }
4252 
4253  } // end switch( ...
4254 
4255 SetStatusAndReturn:
4256 
4257  return status;
4258 }
4259 
4260 
4261 NTSTATUS
4262 NTAPI
4265  IN PIRP Irp
4266  )
4267 
4268 /*++
4269 
4270 Routine Description:
4271 
4272  This routine is called for a shutdown and flush IRPs. These are sent by the
4273  system before it actually shuts down or when the file system does a flush.
4274  If it exists, the device-specific driver's routine will be invoked. If there
4275  wasn't one specified, the Irp will be completed with an Invalid device request.
4276 
4277 Arguments:
4278 
4279  DriverObject - Pointer to device object to being shutdown by system.
4280 
4281  Irp - IRP involved.
4282 
4283 Return Value:
4284 
4285  NT Status
4286 
4287 --*/
4288 
4289 {
4290  PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
4291 
4292  ASSERT(*(PULONG)deviceExtension != '2slc');
4293 
4294  if (deviceExtension->ClassShutdownFlush) {
4295 
4296  //
4297  // Call the device-specific driver's routine.
4298  //
4299 
4300  return deviceExtension->ClassShutdownFlush(DeviceObject, Irp);
4301  }
4302 
4303  //
4304  // Device-specific driver doesn't support this.
4305  //
4306 
4307  Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
4309 
4311 }
4312 
4313 
4314 ULONG
4315 NTAPI
4318  IN PSCSI_ADAPTER_BUS_INFO AdapterInformation
4319  )
4320 
4321 {
4322  ULONG scsiBus,deviceCount = 0;
4323  PCHAR buffer = (PCHAR)AdapterInformation;
4324  PSCSI_INQUIRY_DATA lunInfo;
4325  PINQUIRYDATA inquiryData;
4326 
4327  for (scsiBus=0; scsiBus < (ULONG)AdapterInformation->NumberOfBuses; scsiBus++) {
4328 
4329  //
4330  // Get the SCSI bus scan data for this bus.
4331  //
4332 
4333  lunInfo = (PVOID) (buffer + AdapterInformation->BusData[scsiBus].InquiryDataOffset);
4334 
4335  //
4336  // Search list for unclaimed disk devices.
4337  //
4338 
4339  while (AdapterInformation->BusData[scsiBus].InquiryDataOffset) {
4340 
4341  inquiryData = (PVOID)lunInfo->InquiryData;
4342 
4343  ASSERT(InitializationData->ClassFindDeviceCallBack);
4344 
4345  if ((InitializationData->ClassFindDeviceCallBack(inquiryData)) && (!lunInfo->DeviceClaimed)) {
4346 
4347  deviceCount++;
4348  }
4349 
4350  if (lunInfo->NextInquiryDataOffset == 0) {
4351  break;
4352  }
4353 
4354  lunInfo = (PVOID) (buffer + lunInfo->NextInquiryDataOffset);
4355  }
4356  }
4357  return deviceCount;
4358 }
4359 
4360 
4361 
4362 NTSTATUS
4363 NTAPI
4366  IN PCCHAR ObjectNameBuffer,
4370  )
4371 
4372 /*++
4373 
4374 Routine Description:
4375 
4376  This routine creates an object for the physical device specified and
4377  sets up the deviceExtension's function pointers for each entry point
4378  in the device-specific driver.
4379 
4380 Arguments:
4381 
4382  DriverObject - Pointer to driver object created by system.
4383 
4384  ObjectNameBuffer - Dir. name of the object to create.
4385 
4386  PhysicalDeviceObject - Pointer to the physical (class) device object for
4387  this logical unit or NULL if this is it.
4388 
4389  DeviceObject - Pointer to the device object pointer we will return.
4390 
4391  InitializationData - Pointer to the init data created by the device-specific driver.
4392 
4393 Return Value:
4394 
4395  NTSTATUS
4396 
4397 --*/
4398 
4399 {
4400  STRING ntNameString;
4401  UNICODE_STRING ntUnicodeString;
4402  NTSTATUS status;
4403  PDEVICE_OBJECT deviceObject = NULL;
4404 
4405  *DeviceObject = NULL;
4406 
4407  DebugPrint((2,
4408  "ScsiClassCreateDeviceObject: Create device object %s\n",
4409  ObjectNameBuffer));
4410 
4411  RtlInitString(&ntNameString,
4413 
4414  status = RtlAnsiStringToUnicodeString(&ntUnicodeString,
4415  &ntNameString,
4416  TRUE);
4417 
4418  if (!NT_SUCCESS(status)) {
4419 
4420  DebugPrint((1,
4421  "CreateDiskDeviceObjects: Cannot convert string %s\n",
4422  ObjectNameBuffer));
4423 
4424  ntUnicodeString.Buffer = NULL;
4425  return status;
4426  }
4427 
4429  InitializationData->DeviceExtensionSize,
4430  &ntUnicodeString,
4431  InitializationData->DeviceType,
4432  InitializationData->DeviceCharacteristics,
4433  FALSE,
4434  &deviceObject);
4435 
4436 
4437  if (!NT_SUCCESS(status)) {
4438 
4439  DebugPrint((1,
4440  "CreateDiskDeviceObjects: Can not create device object %s\n",
4441  ObjectNameBuffer));
4442 
4443  } else {
4444 
4445  PDEVICE_EXTENSION deviceExtension = deviceObject->DeviceExtension;
4446 
4447  ASSERT(*(PULONG)deviceExtension != '2slc');
4448 
4449  //
4450  // Fill in entry points
4451  //
4452 
4453  deviceExtension->ClassError = InitializationData->ClassError;
4454  deviceExtension->ClassReadWriteVerification = InitializationData->ClassReadWriteVerification;
4455  deviceExtension->ClassFindDevices = InitializationData->ClassFindDevices;
4456  deviceExtension->ClassDeviceControl = InitializationData->ClassDeviceControl;
4457  deviceExtension->ClassShutdownFlush = InitializationData->ClassShutdownFlush;
4458  deviceExtension->ClassCreateClose = InitializationData->ClassCreateClose;
4459  deviceExtension->ClassStartIo = InitializationData->ClassStartIo;
4460 
4461  deviceExtension->MediaChangeCount = 0;
4462 
4463  //
4464  // If a pointer to the physical device object was passed in then use
4465  // that. If the value was NULL, then this is the physical device so
4466  // use the pointer to the device we just created.
4467  //
4468 
4470  deviceExtension->PhysicalDevice = PhysicalDeviceObject;
4471  } else {
4472  deviceExtension->PhysicalDevice = deviceObject;
4473  }
4474 
4475  deviceExtension->DeviceName = ntUnicodeString;
4476  }
4477 
4478  deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
4479 
4480  *DeviceObject = deviceObject;
4481 
4482  return status;
4483 }
4484 
4485 
4486 NTSTATUS
4487 NTAPI
4489  IN PDEVICE_OBJECT PortDeviceObject,
4490  IN PSCSI_INQUIRY_DATA LunInfo,
4491  IN BOOLEAN Release,
4492  OUT PDEVICE_OBJECT *NewPortDeviceObject OPTIONAL
4493  )
4494 /*++
4495 
4496 Routine Description:
4497 
4498  This function claims a device in the port driver. The port driver object
4499  is updated with the correct driver object if the device is successfully
4500  claimed.
4501 
4502 Arguments:
4503 
4504  PortDeviceObject - Supplies the base port device object.
4505 
4506  LunInfo - Supplies the logical unit inforamtion of the device to be claimed.
4507 
4508  Release - Indicates the logical unit should be released rather than claimed.
4509 
4510  NewPortDeviceObject - Returns the updated port device object to be used
4511  for all future accesses.
4512 
4513 Return Value:
4514 
4515  Returns a status indicating success or failure of the operation.
4516 
4517 --*/
4518 
4519 {
4520  IO_STATUS_BLOCK ioStatus;
4521  PIRP irp;
4522  PIO_STACK_LOCATION irpStack;
4523  KEVENT event;
4524  NTSTATUS status;
4525  SCSI_REQUEST_BLOCK srb;
4526 
4527  PAGED_CODE();
4528 
4529  if (NewPortDeviceObject != NULL) {
4530  *NewPortDeviceObject = NULL;
4531  }
4532 
4533  //
4534  // Clear the SRB fields.
4535  //
4536 
4537  RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK));
4538 
4539  //
4540  // Write length to SRB.
4541  //
4542 
4544 
4545  //
4546  // Set SCSI bus address.
4547  //
4548 
4549  srb.PathId = LunInfo->PathId;
4550  srb.TargetId = LunInfo->TargetId;
4551  srb.Lun = LunInfo->Lun;
4552 
4555 
4556  //
4557  // Set the event object to the unsignaled state.
4558  // It will be used to signal request completion.
4559  //
4560 
4562 
4563  //
4564  // Build synchronous request with no transfer.
4565  //
4566 
4568  PortDeviceObject,
4569  NULL,
4570  0,
4571  NULL,
4572  0,
4573  TRUE,
4574  &event,
4575  &ioStatus);
4576 
4577  if (irp == NULL) {
4578 
4579  DebugPrint((1, "ScsiClassClaimDevice: Can't allocate Irp\n"));
4581  }
4582 
4583  irpStack = IoGetNextIrpStackLocation(irp);
4584 
4585  //
4586  // Save SRB address in next stack for port driver.
4587  //
4588 
4589  irpStack->Parameters.Scsi.Srb = &srb;
4590 
4591  //
4592  // Set up IRP Address.
4593  //
4594 
4595  srb.OriginalRequest = irp;
4596 
4597  //
4598  // Call the port driver with the request and wait for it to complete.
4599  //
4600 
4601  status = IoCallDriver(PortDeviceObject, irp);
4602  if (status == STATUS_PENDING) {
4603 
4605  status = ioStatus.Status;
4606  }
4607 
4608  //
4609  // If this is a release request, then just decrement the reference count
4610  // and return. The status does not matter.
4611  //
4612 
4613  if (Release) {
4614 
4615  //ObDereferenceObject(PortDeviceObject);
4616  return STATUS_SUCCESS;
4617  }
4618 
4619  if (!NT_SUCCESS(status)) {
4620  return status;
4621  }
4622 
4623  ASSERT(srb.DataBuffer != NULL);
4624 
4625  //
4626  // Reference the new port driver object so that it will not go away while
4627  // it is being used.
4628  //
4629 
4631  0,
4632  NULL,
4633  KernelMode );
4634 
4635  if (!NT_SUCCESS(status)) {
4636 
4637  return status;
4638  }
4640 
4641  //
4642  // Return the new port device object pointer.
4643  //
4644 
4645  if (NewPortDeviceObject != NULL) {
4646  *NewPortDeviceObject = srb.DataBuffer;
4647  }
4648 
4649  return status;
4650 }
4651 
4652 
4653 NTSTATUS
4654 NTAPI
4657  IN PIRP Irp
4658  )
4659 
4660 /*++
4661 
4662 Routine Description:
4663 
4664  This routine passes internal device controls to the port driver.
4665  Internal device controls are used by higher level class drivers to
4666  send scsi requests to a device that are not normally sent by a generic
4667  class driver.
4668 
4669  The path ID, target ID and logical unit ID are set in the srb so the
4670  higher level driver does not have to figure out what values are actually
4671  used.
4672 
4673 Arguments:
4674 
4675  DeviceObject - Supplies a pointer to the device object for this request.
4676 
4677  Irp - Supplies the Irp making the request.
4678 
4679 Return Value:
4680 
4681  Returns back a STATUS_PENDING or a completion status.
4682 
4683 --*/
4684 {
4686  PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
4687  PSCSI_REQUEST_BLOCK srb;
4688 
4689  ASSERT(*(PULONG)deviceExtension != '2slc');
4690 
4691  //
4692  // Get a pointer to the SRB.
4693  //
4694 
4695  srb = irpStack->Parameters.Scsi.Srb;
4696 
4697  //
4698  // Set SCSI bus address.
4699  //
4700 
4701  srb->PathId = deviceExtension->PathId;
4702  srb->TargetId = deviceExtension->TargetId;
4703  srb->Lun = deviceExtension->Lun;
4704 
4705  //
4706  // NOTICE: The SCSI-II specification indicates that this field should be
4707  // zero; however, some target controllers ignore the logical unit number
4708  // in the IDENTIFY message and only look at the logical unit number field
4709  // in the CDB.
4710  //
4711 
4712  srb->Cdb[1] |= deviceExtension->Lun << 5;
4713 
4714  //
4715  // Set the parameters in the next stack location.
4716  //
4717 
4718  irpStack = IoGetNextIrpStackLocation(Irp);
4719 
4720  irpStack->Parameters.Scsi.Srb = srb;
4721  irpStack->MajorFunction = IRP_MJ_SCSI;
4722  irpStack->MinorFunction = IRP_MN_SCSI_CLASS;
4723 
4725  return IoCallDriver(deviceExtension->PortDeviceObject, Irp);
4726 }
4727 
4728 NTSTATUS
4729 NTAPI
4732  IN PIRP Irp,
4733  IN PVOID Context
4734  )
4735 
4736 /*++
4737 
4738 Routine Description:
4739 
4740  This routine is called when an internal device control I/O request
4741  has completed. It marks the IRP pending if necessary and returns the
4742  status of the request.
4743 
4744 Arguments:
4745 
4746  DeviceObject - Target device object.
4747 
4748  Irp - Completed request.
4749 
4750  Context - not used.
4751 
4752 Return Value:
4753 
4754  Returns the status of the completed request.
4755 
4756 --*/
4757 
4758 {
4761 
4762  //
4763  // If pending is returned for this Irp then mark current stack
4764  // as pending
4765  //
4766 
4767  if (Irp->PendingReturned) {
4768 
4769  IoMarkIrpPending( Irp );
4770  }
4771 
4772  return Irp->IoStatus.Status;
4773 }
4774 
4775 
4776 VOID
4777 NTAPI
4779  IN PDEVICE_EXTENSION DeviceExtension,
4781  )
4782 
4783 /*++
4784 
4785 Routine Description:
4786 
4787  This routine sets up a lookaside listhead for srbs.
4788 
4789 Arguments:
4790 
4791  DeviceExtension - Pointer to the deviceExtension containing the listhead.
4792 
4793  NumberElements - Supplies the maximum depth of the lookaside list.
4794 
4795 
4796 Return Value:
4797 
4798  None
4799 
4800 --*/
4801 
4802 {
4803  ExInitializeNPagedLookasideList(&DeviceExtension->SrbLookasideListHead,
4804  NULL,
4805  NULL,
4808  'HscS',
4810 
4811 }
4812 
4813 
4814 ULONG
4815 NTAPI
4818  )
4819 
4820 /*++
4821 
4822 Routine Description:
4823 
4824  This routine determines whether a reg key for a user-specified timeout value exists.
4825 
4826 Arguments:
4827 
4828  RegistryPath - Pointer to the hardware reg. entry describing the key.
4829 
4830 Return Value:
4831 
4832  New default timeout for a class of devices.
4833 
4834 --*/
4835 
4836 {
4837  //
4838  // Find the appropriate reg. key
4839  //
4840 
4841  PRTL_QUERY_REGISTRY_TABLE parameters = NULL;
4842  PWSTR path;
4843  NTSTATUS status;
4844  LONG timeOut = 0;
4845  ULONG zero = 0;
4846  ULONG size;
4847 
4848  if (!RegistryPath) {
4849  return 0;
4850  }
4851 
4852  parameters = ExAllocatePool(NonPagedPool,
4853  sizeof(RTL_QUERY_REGISTRY_TABLE)*2);
4854 
4855  if (!parameters) {
4856  return 0;
4857  }
4858 
4859  size = RegistryPath->MaximumLength + sizeof(WCHAR);
4861 
4862  if (!path) {
4863  ExFreePool(parameters);
4864  return 0;
4865  }
4866 
4869 
4870 
4871  //
4872  // Check for the Timeout value.
4873  //
4874 
4875  RtlZeroMemory(parameters,
4876  (sizeof(RTL_QUERY_REGISTRY_TABLE)*2));
4877 
4878  parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
4879  parameters[0].Name = L"TimeOutValue";
4880  parameters[0].EntryContext = &timeOut;
4881  parameters[0].DefaultType = REG_DWORD;
4882  parameters[0].DefaultData = &zero;
4883  parameters[0].DefaultLength = sizeof(ULONG);
4884 
4886  path,
4887  parameters,
4888  NULL,
4889  NULL);
4890 
4891  if (!(NT_SUCCESS(status))) {
4892  timeOut = 0;
4893  }
4894 
4895  ExFreePool(parameters);
4896  ExFreePool(path);
4897 
4898  DebugPrint((2,
4899  "ScsiClassQueryTimeOutRegistryValue: Timeout value %d\n",
4900  timeOut));
4901 
4902 
4903  return timeOut;
4904 
4905 }
4906 
4907 NTSTATUS
4908 NTAPI
4911  IN PIRP Irp,
4912  IN PVOID Context
4913  )
4914 
4915 /*++
4916 
4917 Routine Description:
4918 
4919  This routine executes when the port driver has completed a check verify
4920  ioctl. It will set the status of the master Irp, copy the media change
4921  count and complete the request.
4922 
4923 Arguments:
4924 
4925  DeviceObject - Supplies the device object which represents the logical
4926  unit.
4927 
4928  Irp - Supplies the Irp which has completed.
4929 
4930  Context - NULL
4931 
4932 Return Value:
4933 
4934  NT status
4935 
4936 --*/
4937 
4938 {
4940  PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
4941  PDEVICE_EXTENSION physicalExtension =
4942  deviceExtension->PhysicalDevice->DeviceExtension;
4943  PIRP originalIrp;
4944 
4945  ASSERT(*(PULONG)deviceExtension != '2slc');
4946  ASSERT(*(PULONG)physicalExtension != '2slc');
4947 
4948  originalIrp = irpStack->Parameters.Others.Argument1;
4949 
4950  //
4951  // Copy the media change count and status
4952  //
4953 
4954  *((PULONG) (originalIrp->AssociatedIrp.SystemBuffer)) =
4955  physicalExtension->MediaChangeCount;
4956 
4957  DebugPrint((2, "ScsiClassInterpretSenseInfo - Media change count for"
4958  "device %d is %d\n",
4959  physicalExtension->DeviceNumber,
4960  physicalExtension->MediaChangeCount));
4961 
4962  originalIrp->IoStatus.Status = Irp->IoStatus.Status;
4963  originalIrp->IoStatus.Information = sizeof(ULONG);
4964 
4965  IoCompleteRequest(originalIrp, IO_DISK_INCREMENT);
4966 
4967  IoFreeIrp(Irp);
4968 
4970 }
4971 
4972 NTSTATUS
4973 NTAPI
4975  IN PIRP Irp,
4976  IN PVOID Context)
4977 {
4978  PIO_STATUS_BLOCK IoStatusBlock = Irp->UserIosb;
4979  PKEVENT Event = Irp->UserEvent;
4980  PMDL Mdl;
4981 
4982  *IoStatusBlock = Irp->IoStatus;
4983  Irp->UserIosb = NULL;
4984  Irp->UserEvent = NULL;
4985 
4986  if(Irp->MdlAddress)
4987  {
4988  Mdl = Irp->MdlAddress;
4989 
4990  // if necessary - unlock pages
4991  if ((Mdl->MdlFlags & MDL_PAGES_LOCKED) &&
4992  !(Mdl->MdlFlags & MDL_PARTIAL_HAS_BEEN_MAPPED))
4993  {
4994  MmUnlockPages(Mdl);
4995  }
4996 
4997  // free this mdl
4998  IoFreeMdl(Mdl);
4999  }
5000 
5001  // free irp and set event to unsignaled state
5002  IoFreeIrp(Irp);
5004 
5006 }
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:1640
#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:3558
#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:694
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:4655
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:1966
_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:4778
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:2844
NTSTATUS NTAPI ScsiClassAsynchronousCompletion(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context)
Definition: class2.c:1216
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:1297
#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
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:1122
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:4488
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:4263
#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:462
LARGE_INTEGER DeviceOffset
Definition: iotypes.h:1969
#define PAGED_CODE()
Definition: video.h:57
#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:4730
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:1964
#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:4909
#define IO_DISK_INCREMENT
Definition: iotypes.h:568
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:938
NTSTATUS NTAPI DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
Definition: class2.c:126
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:3295
#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:4974
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:1780
#define STATUS_MEDIA_WRITE_PROTECTED
Definition: udferr_usr.h:161
struct _MODE_PARAMETER_HEADER10 MODE_PARAMETER_HEADER10
VOID NTAPI KeBugCheck(ULONG BugCheckCode)
Definition: bug.c:1427
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:4364
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:3198
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:2867
#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:1955
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:1491
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:4316
#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:2147
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:1560
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:1081
NTSTATUS NTAPI ScsiClassSendSrbAsynchronous(PDEVICE_OBJECT DeviceObject, PSCSI_REQUEST_BLOCK Srb, PIRP Irp, PVOID BufferAddress, ULONG BufferLength, BOOLEAN WriteToDevice)
Definition: class2.c:3369
#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:4157
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:2480
#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:1781
#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:2969
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:2181
#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:566
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:114
#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:3602
VOID NTAPI IoSetHardErrorOrVerifyDevice(IN PIRP Irp, IN PDEVICE_OBJECT DeviceObject)
Definition: util.c:316
PDRIVER_STARTIO DriverStartIo
Definition: iotypes.h:2179
#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:2772
#define SCSI_ADSENSE_ILLEGAL_COMMAND
Definition: cdrw_hw.h:1263
return STATUS_SUCCESS
Definition: btrfs.c:2938
IoMarkIrpPending(Irp)
#define REG_DWORD
Definition: sdbapi.c:596
signed int * PLONG
Definition: retypes.h:5
#define VPB_MOUNTED
Definition: iotypes.h:1764
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:1855
UCHAR UniqueId[1]
Definition: imports.h:139
ULONG NTAPI ScsiClassQueryTimeOutRegistryValue(IN PUNICODE_STRING RegistryPath)
Definition: class2.c:4816
#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
LONGLONG QuadPart
Definition: typedefs.h:113
#define IRP_MJ_DEVICE_CONTROL
Definition: rdpdr.c:52
#define STATUS_DEVICE_NOT_READY
Definition: shellext.h:70
#define SCSI_ADSENSE_MEDIUM_CHANGED
Definition: cdrw_hw.h:1288
VOID NTAPI IoStartNextPacket(IN PDEVICE_OBJECT DeviceObject, IN BOOLEAN Cancelable)
Definition: