mirror of
https://github.com/reactos/reactos.git
synced 2025-05-23 02:56:09 +00:00
Implemented several IOCTLs.
Improved error handling/reporting. svn path=/trunk/; revision=4962
This commit is contained in:
parent
7cc3dd52bb
commit
db571ee907
1 changed files with 258 additions and 27 deletions
|
@ -16,7 +16,7 @@
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
/* $Id: class2.c,v 1.34 2003/05/01 17:49:23 ekohl Exp $
|
/* $Id: class2.c,v 1.35 2003/06/24 21:32:15 ekohl Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -412,9 +412,14 @@ ScsiClassDeviceControl(PDEVICE_OBJECT DeviceObject,
|
||||||
PIRP Irp)
|
PIRP Irp)
|
||||||
{
|
{
|
||||||
PDEVICE_EXTENSION DeviceExtension;
|
PDEVICE_EXTENSION DeviceExtension;
|
||||||
|
PIO_STACK_LOCATION NextStack;
|
||||||
PIO_STACK_LOCATION Stack;
|
PIO_STACK_LOCATION Stack;
|
||||||
ULONG IoControlCode;
|
ULONG IoControlCode;
|
||||||
|
ULONG InputBufferLength;
|
||||||
ULONG OutputBufferLength;
|
ULONG OutputBufferLength;
|
||||||
|
ULONG ModifiedControlCode;
|
||||||
|
PSCSI_REQUEST_BLOCK Srb;
|
||||||
|
PCDB Cdb;
|
||||||
|
|
||||||
DPRINT("ScsiClassDeviceControl() called\n");
|
DPRINT("ScsiClassDeviceControl() called\n");
|
||||||
|
|
||||||
|
@ -422,6 +427,7 @@ ScsiClassDeviceControl(PDEVICE_OBJECT DeviceObject,
|
||||||
Stack = IoGetCurrentIrpStackLocation(Irp);
|
Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
IoControlCode = Stack->Parameters.DeviceIoControl.IoControlCode;
|
IoControlCode = Stack->Parameters.DeviceIoControl.IoControlCode;
|
||||||
|
InputBufferLength = Stack->Parameters.DeviceIoControl.InputBufferLength;
|
||||||
OutputBufferLength = Stack->Parameters.DeviceIoControl.OutputBufferLength;
|
OutputBufferLength = Stack->Parameters.DeviceIoControl.OutputBufferLength;
|
||||||
|
|
||||||
if (IoControlCode == IOCTL_SCSI_GET_ADDRESS)
|
if (IoControlCode == IOCTL_SCSI_GET_ADDRESS)
|
||||||
|
@ -454,17 +460,87 @@ ScsiClassDeviceControl(PDEVICE_OBJECT DeviceObject,
|
||||||
if (IoControlCode == IOCTL_SCSI_PASS_THROUGH ||
|
if (IoControlCode == IOCTL_SCSI_PASS_THROUGH ||
|
||||||
IoControlCode == IOCTL_SCSI_PASS_THROUGH_DIRECT)
|
IoControlCode == IOCTL_SCSI_PASS_THROUGH_DIRECT)
|
||||||
{
|
{
|
||||||
DPRINT1("Fixme: IOCTL_SCSI_PASS_THROUGH/IOCTL_SCSI_PASS_THROUGH_DIRECT\n");
|
PSCSI_PASS_THROUGH ScsiPassThrough;
|
||||||
|
|
||||||
|
DPRINT("IOCTL_SCSI_PASS_THROUGH/IOCTL_SCSI_PASS_THROUGH_DIRECT\n");
|
||||||
|
|
||||||
Irp->IoStatus.Information = 0;
|
/* Check input size */
|
||||||
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
if (InputBufferLength < sizeof(SCSI_PASS_THROUGH))
|
||||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
{
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return(STATUS_INVALID_PARAMETER);
|
||||||
|
}
|
||||||
|
|
||||||
return(STATUS_UNSUCCESSFUL);
|
/* Initialize next stack location for call to the port driver */
|
||||||
|
NextStack = IoGetNextIrpStackLocation(Irp);
|
||||||
|
|
||||||
|
ScsiPassThrough = Irp->AssociatedIrp.SystemBuffer;
|
||||||
|
ScsiPassThrough->PathId = DeviceExtension->PathId;
|
||||||
|
ScsiPassThrough->TargetId = DeviceExtension->TargetId;
|
||||||
|
ScsiPassThrough->Lun = DeviceExtension->Lun;
|
||||||
|
ScsiPassThrough->Cdb[1] |= DeviceExtension->Lun << 5;
|
||||||
|
|
||||||
|
NextStack->Parameters = Stack->Parameters;
|
||||||
|
NextStack->MajorFunction = Stack->MajorFunction;
|
||||||
|
NextStack->MinorFunction = Stack->MinorFunction;
|
||||||
|
|
||||||
|
/* Call port driver */
|
||||||
|
return(IoCallDriver(DeviceExtension->PortDeviceObject,
|
||||||
|
Irp));
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINT1("Fixme: unknown device io control code\n");
|
/* Allocate an SRB */
|
||||||
|
Srb = ExAllocatePool (NonPagedPool,
|
||||||
|
sizeof(SCSI_REQUEST_BLOCK));
|
||||||
|
if (Srb == NULL)
|
||||||
|
{
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
IoCompleteRequest(Irp,
|
||||||
|
IO_NO_INCREMENT);
|
||||||
|
return(STATUS_INSUFFICIENT_RESOURCES);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize the SRB */
|
||||||
|
RtlZeroMemory(Srb,
|
||||||
|
sizeof(SCSI_REQUEST_BLOCK));
|
||||||
|
Cdb = (PCDB)Srb->Cdb;
|
||||||
|
|
||||||
|
ModifiedControlCode = (IoControlCode & 0x0000FFFF) | (IOCTL_DISK_BASE << 16);
|
||||||
|
switch (ModifiedControlCode)
|
||||||
|
{
|
||||||
|
case IOCTL_DISK_CHECK_VERIFY:
|
||||||
|
DPRINT("IOCTL_DISK_CHECK_VERIFY\n");
|
||||||
|
|
||||||
|
/* Initialize SRB operation */
|
||||||
|
Srb->CdbLength = 6;
|
||||||
|
Srb->TimeOutValue = DeviceExtension->TimeOutValue;
|
||||||
|
Cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY;
|
||||||
|
|
||||||
|
return(ScsiClassSendSrbAsynchronous(DeviceObject,
|
||||||
|
Srb,
|
||||||
|
Irp,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
FALSE));
|
||||||
|
|
||||||
|
default:
|
||||||
|
DPRINT1("Unknown device io control code %lx\n",
|
||||||
|
ModifiedControlCode);
|
||||||
|
ExFreePool(Srb);
|
||||||
|
|
||||||
|
/* Pass the IOCTL down to the port driver */
|
||||||
|
NextStack = IoGetNextIrpStackLocation(Irp);
|
||||||
|
NextStack->Parameters = Stack->Parameters;
|
||||||
|
NextStack->MajorFunction = Stack->MajorFunction;
|
||||||
|
NextStack->MinorFunction = Stack->MinorFunction;
|
||||||
|
|
||||||
|
/* Call port driver */
|
||||||
|
return(IoCallDriver(DeviceExtension->PortDeviceObject,
|
||||||
|
Irp));
|
||||||
|
}
|
||||||
|
|
||||||
Irp->IoStatus.Information = 0;
|
Irp->IoStatus.Information = 0;
|
||||||
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
||||||
|
@ -765,7 +841,11 @@ ScsiClassInterpretSenseInfo(PDEVICE_OBJECT DeviceObject,
|
||||||
NTSTATUS *Status)
|
NTSTATUS *Status)
|
||||||
{
|
{
|
||||||
PDEVICE_EXTENSION DeviceExtension;
|
PDEVICE_EXTENSION DeviceExtension;
|
||||||
|
#if 0
|
||||||
|
PIO_ERROR_LOG_PACKET LogPacket;
|
||||||
|
#endif
|
||||||
PSENSE_DATA SenseData;
|
PSENSE_DATA SenseData;
|
||||||
|
BOOLEAN LogError;
|
||||||
BOOLEAN Retry;
|
BOOLEAN Retry;
|
||||||
|
|
||||||
DPRINT("ScsiClassInterpretSenseInfo() called\n");
|
DPRINT("ScsiClassInterpretSenseInfo() called\n");
|
||||||
|
@ -780,6 +860,7 @@ ScsiClassInterpretSenseInfo(PDEVICE_OBJECT DeviceObject,
|
||||||
|
|
||||||
DeviceExtension = DeviceObject->DeviceExtension;
|
DeviceExtension = DeviceObject->DeviceExtension;
|
||||||
SenseData = Srb->SenseInfoBuffer;
|
SenseData = Srb->SenseInfoBuffer;
|
||||||
|
LogError = FALSE;
|
||||||
Retry = TRUE;
|
Retry = TRUE;
|
||||||
|
|
||||||
if ((Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID) &&
|
if ((Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID) &&
|
||||||
|
@ -794,10 +875,44 @@ ScsiClassInterpretSenseInfo(PDEVICE_OBJECT DeviceObject,
|
||||||
switch (SenseData->SenseKey & 0xf)
|
switch (SenseData->SenseKey & 0xf)
|
||||||
{
|
{
|
||||||
/* FIXME: add more sense key codes */
|
/* FIXME: add more sense key codes */
|
||||||
|
#if 0
|
||||||
|
case SCSI_SENSE_NO_SENSE:
|
||||||
|
|
||||||
|
case SCSI_SENSE_RECOVERED_ERROR:
|
||||||
|
#endif
|
||||||
|
|
||||||
case SCSI_SENSE_NOT_READY:
|
case SCSI_SENSE_NOT_READY:
|
||||||
DPRINT("SCSI_SENSE_NOT_READY\n");
|
DPRINT("SCSI_SENSE_NOT_READY\n");
|
||||||
*Status = STATUS_DEVICE_NOT_READY;
|
*Status = STATUS_DEVICE_NOT_READY;
|
||||||
|
switch (SenseData->AdditionalSenseCode)
|
||||||
|
{
|
||||||
|
case SCSI_ADSENSE_LUN_NOT_READY:
|
||||||
|
DPRINT("SCSI_ADSENSE_LUN_NOT_READY\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SCSI_ADSENSE_NO_MEDIA_IN_DEVICE:
|
||||||
|
DPRINT("SCSI_ADSENSE_NO_MEDIA_IN_DEVICE\n");
|
||||||
|
*Status = STATUS_NO_MEDIA_IN_DEVICE;
|
||||||
|
Retry = FALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SCSI_SENSE_MEDIUM_ERROR:
|
||||||
|
DPRINT("SCSI_SENSE_MEDIUM_ERROR\n");
|
||||||
|
*Status = STATUS_DEVICE_DATA_ERROR;
|
||||||
|
Retry = FALSE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SCSI_SENSE_HARDWARE_ERROR:
|
||||||
|
DPRINT("SCSI_SENSE_HARDWARE_ERROR\n");
|
||||||
|
*Status = STATUS_IO_DEVICE_ERROR;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SCSI_SENSE_ILLEGAL_REQUEST:
|
||||||
|
DPRINT("SCSI_SENSE_ILLEGAL_REQUEST\n");
|
||||||
|
*Status = STATUS_INVALID_DEVICE_REQUEST;
|
||||||
|
Retry = FALSE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SCSI_SENSE_UNIT_ATTENTION:
|
case SCSI_SENSE_UNIT_ATTENTION:
|
||||||
|
@ -815,12 +930,16 @@ ScsiClassInterpretSenseInfo(PDEVICE_OBJECT DeviceObject,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SCSI_SENSE_ILLEGAL_REQUEST:
|
case SCSI_SENSE_DATA_PROTECT:
|
||||||
DPRINT("SCSI_SENSE_ILLEGAL_REQUEST\n");
|
DPRINT("SCSI_SENSE_DATA_PROTECT\n");
|
||||||
*Status = STATUS_INVALID_DEVICE_REQUEST;
|
*Status = STATUS_MEDIA_WRITE_PROTECTED;
|
||||||
Retry = FALSE;
|
Retry = FALSE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SCSI_SENSE_ABORTED_COMMAND:
|
||||||
|
DPRINT("SCSI_SENSE_ABORTED_COMMAND\n");
|
||||||
|
*Status = STATUS_IO_DEVICE_ERROR;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
DPRINT1("SCSI error (sense key: %x)\n",
|
DPRINT1("SCSI error (sense key: %x)\n",
|
||||||
|
@ -858,6 +977,7 @@ ScsiClassInterpretSenseInfo(PDEVICE_OBJECT DeviceObject,
|
||||||
default:
|
default:
|
||||||
DPRINT1("SCSI error (SRB status: %x)\n",
|
DPRINT1("SCSI error (SRB status: %x)\n",
|
||||||
SRB_STATUS(Srb->SrbStatus));
|
SRB_STATUS(Srb->SrbStatus));
|
||||||
|
LogError = TRUE;
|
||||||
*Status = STATUS_IO_DEVICE_ERROR;
|
*Status = STATUS_IO_DEVICE_ERROR;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -872,11 +992,47 @@ ScsiClassInterpretSenseInfo(PDEVICE_OBJECT DeviceObject,
|
||||||
&Retry);
|
&Retry);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: log severe errors */
|
if (LogError == TRUE)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
/* Allocate error packet */
|
||||||
|
LogPacket = IoAllocateErrorLogEntry (DeviceObject,
|
||||||
|
sizeof(IO_ERROR_LOG_PACKET) +
|
||||||
|
5 * sizeof(ULONG));
|
||||||
|
if (LogPacket == NULL)
|
||||||
|
{
|
||||||
|
DPRINT1 ("Failed to allocate a log packet!\n");
|
||||||
|
return Retry;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize error packet */
|
||||||
|
LogPacket->MajorFunctionCode = MajorFunctionCode;
|
||||||
|
LogPacket->RetryCount = (UCHAR)RetryCount;
|
||||||
|
LogPacket->DumpDataSize = 6 * sizeof(ULONG);
|
||||||
|
LogPacket->ErrorCode = 0; /* FIXME */
|
||||||
|
LogPacket->FinalStatus = *Status;
|
||||||
|
LogPacket->IoControlCode = IoDeviceCode;
|
||||||
|
LogPacket->DeviceOffset.QuadPart = 0; /* FIXME */
|
||||||
|
LogPacket->DumpData[0] = Srb->PathId;
|
||||||
|
LogPacket->DumpData[1] = Srb->TargetId;
|
||||||
|
LogPacket->DumpData[2] = Srb->Lun;
|
||||||
|
LogPacket->DumpData[3] = 0;
|
||||||
|
LogPacket->DumpData[4] = (Srb->SrbStatus << 8) | Srb->ScsiStatus;
|
||||||
|
if (SenseData != NULL)
|
||||||
|
{
|
||||||
|
LogPacket->DumpData[5] = (SenseData->SenseKey << 16) |
|
||||||
|
(SenseData->AdditionalSenseCode << 8) |
|
||||||
|
SenseData->AdditionalSenseCodeQualifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write error packet */
|
||||||
|
IoWriteErrorLogEntry (LogPacket);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
DPRINT("ScsiClassInterpretSenseInfo() done\n");
|
DPRINT("ScsiClassInterpretSenseInfo() done\n");
|
||||||
|
|
||||||
return(Retry);
|
return Retry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -898,9 +1054,11 @@ ScsiClassIoComplete(PDEVICE_OBJECT DeviceObject,
|
||||||
|
|
||||||
IrpStack = IoGetCurrentIrpStackLocation(Irp);
|
IrpStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
//BUGBUG -> Srb = IrpStack->Parameters.Scsi.Srb;
|
/*
|
||||||
//Must pass Srb as Context arg!! See comment about Completion routines in
|
* BUGBUG -> Srb = IrpStack->Parameters.Scsi.Srb;
|
||||||
//IofCallDriver for more info.
|
* Must pass Srb as Context arg!! See comment about Completion routines in
|
||||||
|
* IofCallDriver for more info.
|
||||||
|
*/
|
||||||
|
|
||||||
Srb = (PSCSI_REQUEST_BLOCK)Context;
|
Srb = (PSCSI_REQUEST_BLOCK)Context;
|
||||||
|
|
||||||
|
@ -983,9 +1141,11 @@ ScsiClassIoCompleteAssociated(PDEVICE_OBJECT DeviceObject,
|
||||||
|
|
||||||
IrpStack = IoGetCurrentIrpStackLocation(Irp);
|
IrpStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
//BUGBUG -> Srb = Srb = IrpStack->Parameters.Scsi.Srb;
|
/*
|
||||||
//Must pass Srb as Context arg!! See comment about Completion routines in
|
* BUGBUG -> Srb = Srb = IrpStack->Parameters.Scsi.Srb;
|
||||||
//IofCallDriver for more info.
|
* Must pass Srb as Context arg!! See comment about Completion routines in
|
||||||
|
* IofCallDriver for more info.
|
||||||
|
*/
|
||||||
|
|
||||||
Srb = (PSCSI_REQUEST_BLOCK)Context;
|
Srb = (PSCSI_REQUEST_BLOCK)Context;
|
||||||
|
|
||||||
|
@ -1010,11 +1170,10 @@ ScsiClassIoCompleteAssociated(PDEVICE_OBJECT DeviceObject,
|
||||||
{
|
{
|
||||||
((ULONG)IrpStack->Parameters.Others.Argument4)--;
|
((ULONG)IrpStack->Parameters.Others.Argument4)--;
|
||||||
|
|
||||||
ScsiClassRetryRequest(
|
ScsiClassRetryRequest(DeviceObject,
|
||||||
DeviceObject,
|
Irp,
|
||||||
Irp,
|
Srb,
|
||||||
Srb,
|
TRUE);
|
||||||
TRUE);
|
|
||||||
|
|
||||||
return(STATUS_MORE_PROCESSING_REQUIRED);
|
return(STATUS_MORE_PROCESSING_REQUIRED);
|
||||||
}
|
}
|
||||||
|
@ -1260,7 +1419,79 @@ ScsiClassSendSrbAsynchronous(PDEVICE_OBJECT DeviceObject,
|
||||||
ULONG BufferLength,
|
ULONG BufferLength,
|
||||||
BOOLEAN WriteToDevice)
|
BOOLEAN WriteToDevice)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED;
|
PDEVICE_EXTENSION DeviceExtension;
|
||||||
|
PIO_STACK_LOCATION Stack;
|
||||||
|
|
||||||
|
DPRINT("ScsiClassSendSrbAsynchronous() called\n");
|
||||||
|
|
||||||
|
DeviceExtension = DeviceObject->DeviceExtension;
|
||||||
|
|
||||||
|
/* Initialize the SRB */
|
||||||
|
Srb->Length = SCSI_REQUEST_BLOCK_SIZE;
|
||||||
|
Srb->PathId = DeviceExtension->PathId;
|
||||||
|
Srb->TargetId = DeviceExtension->TargetId;
|
||||||
|
Srb->Lun = DeviceExtension->Lun;
|
||||||
|
Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
|
||||||
|
Srb->Cdb[1] |= DeviceExtension->Lun << 5;
|
||||||
|
|
||||||
|
Srb->SenseInfoBuffer = DeviceExtension->SenseData;
|
||||||
|
Srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE;
|
||||||
|
|
||||||
|
Srb->DataBuffer = BufferAddress;
|
||||||
|
Srb->DataTransferLength = BufferLength;
|
||||||
|
|
||||||
|
Srb->ScsiStatus = 0;
|
||||||
|
Srb->SrbStatus = 0;
|
||||||
|
Srb->NextSrb = NULL;
|
||||||
|
|
||||||
|
if (BufferAddress != NULL)
|
||||||
|
{
|
||||||
|
if (Irp->MdlAddress == NULL)
|
||||||
|
{
|
||||||
|
/* Allocate an MDL */
|
||||||
|
if (!IoAllocateMdl(BufferAddress,
|
||||||
|
BufferLength,
|
||||||
|
FALSE,
|
||||||
|
FALSE,
|
||||||
|
Irp))
|
||||||
|
{
|
||||||
|
DPRINT1("Mdl-Allocation failed\n");
|
||||||
|
return(STATUS_INSUFFICIENT_RESOURCES);
|
||||||
|
}
|
||||||
|
|
||||||
|
MmBuildMdlForNonPagedPool(Irp->MdlAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set data direction */
|
||||||
|
Srb->SrbFlags = (WriteToDevice) ? SRB_FLAGS_DATA_OUT : SRB_FLAGS_DATA_IN;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Set data direction */
|
||||||
|
Srb->SrbFlags = SRB_FLAGS_NO_DATA_TRANSFER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the retry counter */
|
||||||
|
Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
Stack->Parameters.Others.Argument4 = (PVOID)MAXIMUM_RETRIES;
|
||||||
|
|
||||||
|
/* Set the completion routine */
|
||||||
|
IoSetCompletionRoutine(Irp,
|
||||||
|
ScsiClassIoComplete,
|
||||||
|
Srb,
|
||||||
|
TRUE,
|
||||||
|
TRUE,
|
||||||
|
TRUE);
|
||||||
|
|
||||||
|
/* Attach Srb to the Irp */
|
||||||
|
Stack = IoGetNextIrpStackLocation(Irp);
|
||||||
|
Stack->MajorFunction = IRP_MJ_SCSI;
|
||||||
|
Stack->Parameters.Scsi.Srb = Srb;
|
||||||
|
Srb->OriginalRequest = Irp;
|
||||||
|
|
||||||
|
/* Call the port driver */
|
||||||
|
return(IoCallDriver(DeviceExtension->PortDeviceObject,
|
||||||
|
Irp));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue