class2.c
来自「一个类似windows」· C语言 代码 · 共 2,461 行 · 第 1/5 页
C
2,461 行
* RUN LEVEL
* PASSIVE_LEVEL
*
* ARGUMENTS
* DeviceExtension
* Class specific device extension.
*
* NumberElements
* Maximum number of elements of the lookaside list.
*
* RETURN VALUE
* None.
*
* @implemented
*/
VOID STDCALL
ScsiClassInitializeSrbLookasideList(IN PDEVICE_EXTENSION DeviceExtension,
IN ULONG NumberElements)
{
ExInitializeNPagedLookasideList(&DeviceExtension->SrbLookasideListHead,
NULL,
NULL,
NonPagedPool,
sizeof(SCSI_REQUEST_BLOCK) + sizeof(SENSE_DATA) + SENSEINFO_ALIGNMENT - 1,
TAG_SRBT,
(USHORT)NumberElements);
}
/*
* @unimplemented
*/
NTSTATUS STDCALL
ScsiClassInternalIoControl(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
DPRINT("ScsiClassInternalIoContol() called\n");
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return(STATUS_SUCCESS);
}
/*
* Implements part of the directives on:
* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/kmarch/hh/kmarch/other_c694d732-fa95-4841-8d61-2a55ee787905.xml.asp
*/
static VOID
ScsiClassInvalidateMedia(IN PDEVICE_OBJECT DeviceObject,
OUT NTSTATUS *Status)
{
PDEVICE_EXTENSION DeviceExtension;
PDEVICE_EXTENSION PhysicalExtension;
DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
PhysicalExtension = (PDEVICE_EXTENSION)DeviceExtension->PhysicalDevice->DeviceExtension;
if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)
{
DPRINT("Invalidate: test char yields TRUE\n");
}
else
{
DPRINT("Invalidate: test char yields FALSE\n");
}
if ((DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) &&
(DeviceObject->Vpb->Flags & VPB_MOUNTED))
{
DPRINT("Set DO_VERIFY_VOLUME\n");
DeviceObject->Flags |= DO_VERIFY_VOLUME;
*Status = STATUS_VERIFY_REQUIRED;
}
else
{
*Status = STATUS_IO_DEVICE_ERROR;
}
/* Increment the media change count */
PhysicalExtension->MediaChangeCount++;
}
/*
* @implemented
*/
BOOLEAN STDCALL
ScsiClassInterpretSenseInfo(IN PDEVICE_OBJECT DeviceObject,
IN PSCSI_REQUEST_BLOCK Srb,
IN UCHAR MajorFunctionCode,
IN ULONG IoDeviceCode,
IN ULONG RetryCount,
OUT NTSTATUS *Status)
{
PDEVICE_EXTENSION DeviceExtension;
PDEVICE_EXTENSION PhysicalExtension;
#if 0
PIO_ERROR_LOG_PACKET LogPacket;
#endif
PSENSE_DATA SenseData;
BOOLEAN LogError;
BOOLEAN Retry;
DPRINT("ScsiClassInterpretSenseInfo() called\n");
DPRINT("Srb->SrbStatus %lx\n", Srb->SrbStatus);
if (SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_PENDING)
{
*Status = STATUS_SUCCESS;
return(FALSE);
}
DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
PhysicalExtension = (PDEVICE_EXTENSION)DeviceExtension->PhysicalDevice->DeviceExtension;
SenseData = Srb->SenseInfoBuffer;
LogError = FALSE;
Retry = TRUE;
if ((Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID) &&
(Srb->SenseInfoBufferLength > 0))
{
/* Got valid sense data, interpret them */
DPRINT("ErrorCode: %x\n", SenseData->ErrorCode);
DPRINT("SenseKey: %x\n", SenseData->SenseKey);
DPRINT("SenseCode: %x\n", SenseData->AdditionalSenseCode);
switch (SenseData->SenseKey & 0xf)
{
case SCSI_SENSE_NO_SENSE:
DPRINT("SCSI_SENSE_NO_SENSE\n");
if (SenseData->IncorrectLength)
{
DPRINT("Incorrect block length\n");
*Status = STATUS_INVALID_BLOCK_LENGTH;
Retry = FALSE;
}
else
{
DPRINT("Unspecified error\n");
*Status = STATUS_IO_DEVICE_ERROR;
Retry = FALSE;
}
break;
case SCSI_SENSE_RECOVERED_ERROR:
DPRINT("SCSI_SENSE_RECOVERED_ERROR\n");
*Status = STATUS_SUCCESS;
Retry = FALSE;
break;
case SCSI_SENSE_NOT_READY:
DPRINT("SCSI_SENSE_NOT_READY\n");
*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");
ScsiClassInvalidateMedia(DeviceObject,
Status);
*Status = STATUS_NO_MEDIA_IN_DEVICE;
Retry = FALSE;
if((DeviceExtension->MediaChangeEvent != NULL) &&
(!DeviceExtension->MediaChangeEvent))
{
KeSetEvent(DeviceExtension->MediaChangeEvent,
0,
FALSE);
DeviceExtension->MediaChangeNoMedia = TRUE;
}
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;
switch (SenseData->AdditionalSenseCode)
{
case SCSI_ADSENSE_ILLEGAL_COMMAND:
DPRINT("SCSI_ADSENSE_ILLEGAL_COMMAND\n");
Retry = FALSE;
break;
case SCSI_ADSENSE_ILLEGAL_BLOCK:
DPRINT("SCSI_ADSENSE_ILLEGAL_BLOCK\n");
*Status = STATUS_NONEXISTENT_SECTOR;
Retry = FALSE;
break;
case SCSI_ADSENSE_INVALID_LUN:
DPRINT("SCSI_ADSENSE_INVALID_LUN\n");
*Status = STATUS_NO_SUCH_DEVICE;
Retry = FALSE;
break;
case SCSI_ADSENSE_MUSIC_AREA:
DPRINT("SCSI_ADSENSE_MUSIC_AREA\n");
Retry = FALSE;
break;
case SCSI_ADSENSE_DATA_AREA:
DPRINT("SCSI_ADSENSE_DATA_AREA\n");
Retry = FALSE;
break;
case SCSI_ADSENSE_VOLUME_OVERFLOW:
DPRINT("SCSI_ADSENSE_VOLUME_OVERFLOW\n");
Retry = FALSE;
break;
case SCSI_ADSENSE_INVALID_CDB:
DPRINT("SCSI_ADSENSE_INVALID_CDB\n");
Retry = FALSE;
break;
}
break;
case SCSI_SENSE_UNIT_ATTENTION:
DPRINT("SCSI_SENSE_UNIT_ATTENTION\n");
switch (SenseData->AdditionalSenseCode)
{
case SCSI_ADSENSE_MEDIUM_CHANGED:
DPRINT("SCSI_ADSENSE_MEDIUM_CHANGED\n");
if(DeviceExtension->MediaChangeEvent != NULL)
{
KeSetEvent(DeviceExtension->MediaChangeEvent,
0,
FALSE);
DeviceExtension->MediaChangeNoMedia = FALSE;
}
break;
case SCSI_ADSENSE_BUS_RESET:
DPRINT("SCSI_ADSENSE_BUS_RESET\n");
break;
default:
DPRINT("Unit attention\n");
break;
}
ScsiClassInvalidateMedia(DeviceObject,
Status);
Retry = FALSE;
break;
case SCSI_SENSE_DATA_PROTECT:
DPRINT("SCSI_SENSE_DATA_PROTECT\n");
*Status = STATUS_MEDIA_WRITE_PROTECTED;
Retry = FALSE;
break;
case SCSI_SENSE_ABORTED_COMMAND:
DPRINT("SCSI_SENSE_ABORTED_COMMAND\n");
*Status = STATUS_IO_DEVICE_ERROR;
break;
default:
DPRINT("SCSI error (sense key: %x)\n",
SenseData->SenseKey & 0xf);
*Status = STATUS_IO_DEVICE_ERROR;
break;
}
}
else
{
/* Got no or invalid sense data, return generic error codes */
switch (SRB_STATUS(Srb->SrbStatus))
{
/* FIXME: add more srb status codes */
case SRB_STATUS_INVALID_PATH_ID:
case SRB_STATUS_INVALID_TARGET_ID:
case SRB_STATUS_INVALID_LUN:
case SRB_STATUS_NO_DEVICE:
case SRB_STATUS_NO_HBA:
*Status = STATUS_NO_SUCH_DEVICE;
Retry = FALSE;
break;
case SRB_STATUS_BUSY:
*Status = STATUS_DEVICE_BUSY;
Retry = TRUE;
break;
case SRB_STATUS_DATA_OVERRUN:
*Status = STATUS_DATA_OVERRUN;
Retry = FALSE;
break;
case SRB_STATUS_INVALID_REQUEST:
*Status = STATUS_INVALID_DEVICE_REQUEST;
Retry = FALSE;
break;
default:
DPRINT("SCSI error (SRB status: %x)\n",
SRB_STATUS(Srb->SrbStatus));
LogError = TRUE;
*Status = STATUS_IO_DEVICE_ERROR;
break;
}
}
/* Call the class driver specific error function */
if (DeviceExtension->ClassError != NULL)
{
DeviceExtension->ClassError(DeviceObject,
Srb,
Status,
&Retry);
}
if (LogError == TRUE)
{
#if 0
/* Allocate error packet */
LogPacket = IoAllocateErrorLogEntry (DeviceObject,
sizeof(IO_ERROR_LOG_PACKET) +
5 * sizeof(ULONG));
if (LogPacket == NULL)
{
DPRINT ("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");
return Retry;
}
/*
* @implemented
*/
NTSTATUS STDCALL
ScsiClassIoComplete(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context)
{
PDEVICE_EXTENSION DeviceExtension;
PIO_STACK_LOCATION IrpStack;
PSCSI_REQUEST_BLOCK Srb;
BOOLEAN Retry;
NTSTATUS Status;
DPRINT("ScsiClassIoComplete(DeviceObject %p Irp %p Context %p) called\n",
DeviceObject, Irp, Context);
DeviceExtension = DeviceObject->DeviceExtension;
IrpStack = IoGetCurrentIrpStackLocation(Irp);
/*
* BUGBUG -> Srb = IrpStack->Parameters.Scsi.Srb;
* Must pass Srb as Context arg!! See comment about Completion routines in
* IofCallDriver for more info.
*/
Srb = (PSCSI_REQUEST_BLOCK)Context;
DPRINT("Srb %p\n", Srb);
if (SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_SUCCESS)
{
Status = STATUS_SUCCESS;
}
else
{
/* Release the queue if it is frozen */
if (Srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN)
{
ScsiClassReleaseQueue (DeviceObject);
}
/* Get more detailed status information */
Retry = ScsiClassInterpretSenseInfo(DeviceObject,
Srb,
IrpStack->MajorFunction,
0,
MAXIMUM_RETRIES - ((ULONG)IrpStack->Parameters.Others.Argument4),
&Status);
/* Retry the request if verify should be overridden */
if ((IrpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME) &&
Status == STATUS_VERIFY_REQUIRED)
{
Status = STATUS_IO_DEVICE_ERROR;
Retry = TRUE;
}
/* Retry the request */
if ((Retry) &&
((ULONG_PTR)IrpStack->Parameters.Others.Argument4 > 0))
{
IrpStack->Parameters.Others.Argument4 = (PVOID) ((ULONG_PTR)IrpStack->Parameters.Others.Argument4 - 1);
ScsiClassRetryRequest(DeviceObject,
Irp,
Srb,
FALSE);
return(STATUS_MORE_PROCESSING_REQUIRED);
}
}
/* Free the SRB */
ExFreeToNPagedLookasideList(&DeviceExtension->SrbLookasideListHead,
Srb);
Irp->IoStatus.Status = Status;
if (!NT_SUCCESS(Status))
{
Irp->IoStatus.Information = 0;
if (IoIsErrorUserInduced(Status))
{
IoSetHardErrorOrVerifyDevice(Irp,
DeviceObject);
}
}
if (Irp->PendingReturned)
{
IoMarkIrpPending (Irp);
}
if (DeviceExtension->ClassStartIo != NULL)
{
if (IrpStack->MajorFunction != IRP_MJ_DEVICE_CONTROL)
{
KIRQL oldIrql;
oldIrql = KeGetCurrentIrql();
if (oldIrql < DISPATCH_LEVEL)
{
KeRaiseIrql (DISPATCH_LEVEL, &oldIrql);
IoStartNextPacket (DeviceObject, FALSE);
KeLowerIrql(oldIrql);
}
else
{
IoStartNextPacket (DeviceObject, FALSE);
}
}
}
DPRINT("ScsiClassIoComplete() done (Status %lx)\n", Status);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?