⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vdiskmp.c

📁 SCSI 的虚拟磁盘驱动 需要 windows DDK 很易懂的 DDK 文件结构
💻 C
📖 第 1 页 / 共 5 页
字号:
            Srb->SrbStatus = SRB_STATUS_SUCCESS;
            break;
        }
        case SCSIOP_REQUEST_SENSE:
            IF_SCSI(KdPrint(("VdiskMpStartIo: SCSIOP_REQUEST_SENSE\r\n"));)
            // Try to build the sense buffer
            if ((Srb->DataBuffer != NULL) && (Srb->DataTransferLength >= sizeof (SENSE_DATA)) )
            {    
                RtlCopyMemory( Srb->DataBuffer, &(Lun->SenseData), sizeof(SENSE_DATA) );
                // All OK
                Srb->SrbStatus = SRB_STATUS_SUCCESS;
                Srb->DataTransferLength = sizeof(SENSE_DATA);
            }
            else
                // Fail the request.
		        Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
            break;
        case SCSIOP_INQUIRY:
            IF_SCSI(KdPrint(("VdiskMpStartIo     : SCSIOP_INQUIRY\r\r\n"));)
			IF_SCSI(KdPrint(("VdiskMpStartIo     : This must not be called by VSPORT- "
                     "VdiskMpInquiry will be called instead\r\r\n"));)
            // Zero the INQUIRY data
            RtlZeroMemory(Srb->DataBuffer, Srb->DataTransferLength);
            // Process it
            VdiskInquiry((PINQUIRYDATA)Srb->DataBuffer);
            // Return SUCCESS
            Srb->SrbStatus = SRB_STATUS_SUCCESS;
            break;
        case SCSIOP_READ:
        case SCSIOP_WRITE:
            // Check ReadOnly flag
            if ((Srb->Cdb[0] == SCSIOP_WRITE) && (Lun->Flags & VDISK_LUN_READ_ONLY))
            {
                KdPrint(("VdiskMpStartIo     : Can't write. Disk is READ_ONLY Flags 0x%X\r\n",
                    Lun->Flags));
                // Return sense data
                VdiskFillSenseData(&Lun->SenseData, Srb, SCSI_ADWRITE_PROTECT);
                break;
            }
            // Get start sector from CDB
            Start = ((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte3 |
                    (((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte2 << 8 ) |
                    (((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte1 << 16 ) |
                    (((PCDB)Srb->Cdb)->CDB10.LogicalBlockByte0 << 24 );
            // Get maximimal sector of the disk
            MaxSector = Lun->DiskSize;                           
            // Calc sectors count
            BlockCount = (USHORT)((Srb->DataTransferLength + 512 - 1 ) / 512);
            // Check Lun flags
            if( Lun->Flags & VDISK_LUN_SHUTDOWN )
            {
                KdPrint(("VdiskMpStartIo     : Lun 0x%X shutdown. Can't read %u sectors from %u\r\n",
                            Lun, BlockCount, Start));
                // Return sense data
                // Do not return "no media" status if the underlying volume is dismounted,
                //  since this status is IoIsErrorUserInduced and the OS will try to show
                //  a popup during shutdown, which will hang
                if( Lun->Flags & VDISK_LUN_DISMOUNT )
                    // Emulate device being disappeared
                    Srb->SrbStatus = SRB_STATUS_SELECTION_TIMEOUT;
                else
                    // CHECK CONDITION with no media
                    VdiskFillSenseData(&Lun->SenseData, Srb, SCSI_ADSENSE_NO_MEDIA_IN_DEVICE);
                break;
            }
	        // Check sectors range and correct sector count
	        if ((Start + BlockCount >= MaxSector) || (Start >= MaxSector))
                if (Start >= MaxSector)
                {
			        KdPrint(("VdiskMpStartIo     :  Error in sector's number %d\r\n", Start));
                    // Clear. Nothing transferred.
                    Srb->DataTransferLength = 0;
			        VdiskFillSenseData(&Lun->SenseData, Srb, SCSI_ADSENSE_ILLEGAL_BLOCK);
                    break;
		        }
                else
			        // lower sector's count 
			        BlockCount = (USHORT)(MaxSector-Start);
            // Request is the SRB_EXTENSION
			Request = (PVDISK_LUN_REQUEST)Srb->SrbExtension;
            // Check pointer	
            if (Request == NULL)
            {
			    KdPrint(("VdiskMpStartIo     :  Error: SRB_EXTENSION is NULL\r\n"));
                // Clear. Nothing transferred.
                Srb->DataTransferLength = 0;
		        VdiskFillSenseData(&Lun->SenseData, Srb, SCSI_ADSENSE_NO_SENSE);
                break;
			}
            // Set up the SRB extension
            Request->ParamTransferBuffer = (ULONG)Srb->DataBuffer;
            if ((PVOID)Request->ParamTransferBuffer == NULL)
            {
                // VSPORT wrong buffer
                // Clear. Nothing transferred.
                Srb->DataTransferLength = 0;
		        VdiskFillSenseData(&Lun->SenseData, Srb, SCSI_ADSENSE_NO_SENSE);
                break;
            }
            // Request haven't completed yet
            Srb->SrbStatus = SRB_STATUS_PENDING;
            // Fill the request's paremeters
            Request->RequestCode = (Srb->Cdb[0] == SCSIOP_READ) ? VDISK_REQUEST_READ:VDISK_REQUEST_WRITE;
			Request->Offset.QuadPart = Start * 512;
			Request->ParamTransferLen = BlockCount;
			Request->ParamTransferSrb = (ULONG)Srb;
            // Submit operation. It's DPC_LEVEL now.
            VdiskRequestSubmit(Request, Lun); 
            IF_1(KdPrint(("VdiskMpStartIo     : SCSIOP_%s submitted %u sectors from %u\r\n",
                    (Srb->Cdb[0]==SCSIOP_READ)?"READ":"WRITE", BlockCount, Start));)
            break;
        case SCSIOP_MODE_SENSE:
            IF_SCSI(KdPrint(("VdiskMpStartIo     : SCSIOP_MODE_SENSE\r\n"));)
            Srb->SrbStatus = SRB_STATUS_SUCCESS;
			Srb->DataTransferLength = sizeof (MODE_PARAMETER_HEADER);
			if (Lun->Flags & VDISK_LUN_READ_ONLY)
            {
                // Device is write-protected, set bit in mode sense buffer
				((PMODE_PARAMETER_HEADER)Srb->DataBuffer)->DeviceSpecificParameter |= MODE_DSP_WRITE_PROTECT;
            }
            // All other fields are 0
            break;
        case SCSIOP_REPORT_LUNS:
            // Cdb[6]...Cdb[9] - Buffer length (Big endian)
            // If SCSIOP_REPORT_LUNS command is supported in the VdiskMpInquiry so we don't need to support it there.
            KdPrint(("VdiskMpStartIo     : SCSIOP_REPORT_LUNS. Fail it. It is supported in the Inquiry LUN\r\n"));
#ifdef DEBUGLEVEL_SCSI
            goto NotSupported;
        case SCSIOP_MODE_SELECT:
            KdPrint(("VdiskMpStartIo     : SCSIOP_MODE_SELECT\r\n"));
            goto NotSupported;
        // Windows XP sends IOCTLs below
        case SCSIOP_LOAD_UNLOAD:
            KdPrint(("VdiskMpStartIo     : SCSIOP_LOAD_UNLOAD\r\n"));
            goto NotSupported;
        case SCSIOP_SYNCHRONIZE_CACHE:
            KdPrint(("VdiskMpStartIo     : SCSIOP_SYNCHRONIZE_CACHE\r\n"));
NotSupported:
#endif
        default:
            KdPrint(("VdiskMpStartIo     : CDB Command 0x%X (%u) isn't supported.\r\n", 
                Srb->Cdb[0], Srb->Cdb[0]));
            // Return upsupported operation.
            Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
            break;
		}
        break;
	case SRB_FUNCTION_ABORT_COMMAND:
        IF_SCSI(KdPrint(("VdiskMpStartIo     : ABORT_COMMAND is not supported\r\n"));)
        // We do not allow aborting.
		Srb->SrbStatus = SRB_STATUS_ABORT_FAILED;
		break;
    case SRB_FUNCTION_IO_CONTROL:
        
		// NT doesn't have this IOCTL:
		//if (IOCTL_STORAGE_PREDICT_FAILURE == ((PSRB_IO_CONTROL)Srb->DataBuffer)->ControlCode)
        //    KdPrint(("VdiskMpStartIo     : IOCTL_STORAGE_PREDICT_FAILURE detected\r\n"));
        
		// Fail the request.
		Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
		break;
	default:
        KdPrint(("VdiskMpStartIo     : SCSI Function %u(0x%X) isn't supported. Error.\r\n", 
                    Srb->Function, Srb->Function));
        // Fail the request.
		Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
		break;
	}
Failed:
    if (Srb->SrbStatus != SRB_STATUS_PENDING)
    {
        IF_1(KdPrint(("VdiskMpStartIo     : Request completed. SrbStatus=0x%X\r\n", Srb->SrbStatus));)
        // Complete or fail the SRB on error
        VsPortCompleteRequest(DeviceExtension, Srb);
    }
    // LUN ready for next request.
	VsPortNextLunRequest(DeviceExtension, 0, TargetId, LunId);
}

///////////////////////////////////////////////////////////////////////////////
// Function fills the inquiry buffer
//
static VOID VdiskInquiry(PINQUIRYDATA InquiryData)
{
    ULONG Index;
    ASSERT(InquiryData);
    // Set HiSupport bit (we support REPORT LUNs)
    ((PUCHAR)InquiryData)[3] = ((PUCHAR)InquiryData)[3] | 0x10;
    // Build the INQUIRY data
    InquiryData->DeviceType = DIRECT_ACCESS_DEVICE;
    // Set vendor ID
    RtlCopyMemory(InquiryData->VendorId, "SCI INC ", 8);
	// Set product ID
	RtlCopyMemory(InquiryData->ProductId, "VIRTUAL DISK    ", 16);
	// Set revision level
    RtlCopyMemory(InquiryData->ProductRevisionLevel, "0003", 4);
	// Clear this out for now; future information will go here.
    for ( Index = 0; Index < 20; Index++ )
        InquiryData->VendorSpecific[ Index ] = ' ';
}

///////////////////////////////////////////////////////////////////////////////
// VSPORT calls this function to investigate LUN existence
// 
static UCHAR VdiskMpInquiry(IN PVOID DeviceExtension, IN PSCSI_REQUEST_BLOCK InquirySrb)
{
    KdPrint(("VdiskMpInquiry enter...\r\n"));
    // Support for SCSI-3 REPORT LUN command
    if( InquirySrb->Cdb[0] == SCSIOP_REPORT_LUNS )
    {
        if(InquirySrb->DataTransferLength < 16)
        {
            KdPrint(("VdiskMpInquiry: SCSIOP_REPORT_LUNS query passed a small buffer. Fail it.\r\n"));
            // Too small
            InquirySrb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
        }
        else
        {
            PULONG DataBuffer = (PULONG)InquirySrb->DataBuffer;
            ULONG Supremum = (ULONG)InquirySrb->DataBuffer+(ULONG)InquirySrb->DataTransferLength;
            ULONG Lun;
            // Number_of_LUNs * 8 is in the first 4 bytes and big endian
            *DataBuffer++ = VdiskChangeBytes(NUMBER_OF_LUNS * 8);
            // Reserved room
            *DataBuffer++ = 0;
            // Put numbers of supported LUNs.
            // We just put there every LUN which we can have, but we can read Registry and put only available LUNs
            for( Lun=0; (Lun<NUMBER_OF_LUNS) && ((ULONG)DataBuffer+7<Supremum); Lun++)
            {
                // Lower byte is reported LUN number
                *DataBuffer++ = Lun;
                // The others bytes are reserved
                *DataBuffer++ = 0;
            }
            KdPrint(("VdiskMpInquiry: %d LUNs reported because output buffer size is %d.\r\n", Lun, InquirySrb->DataTransferLength));
            // Return SUCCESS
            InquirySrb->SrbStatus = SRB_STATUS_SUCCESS;
        }
        return InquirySrb->SrbStatus;
    }
    // Check the LUN existence and start the LUN's thread
    if ( (InquirySrb->TargetId < NUMBER_OF_TARGETS) && (InquirySrb->Lun < NUMBER_OF_LUNS) &&
        NT_SUCCESS(VdiskInquiryLun(DeviceExtension, InquirySrb->TargetId, InquirySrb->Lun)))
    {
        // LUN already filled in the 
        KdPrint(("VdiskMpInquiry: Reqistry scanned ok.\r\n"));
        // Zero the INQUIRY data
        RtlZeroMemory(InquirySrb->DataBuffer, InquirySrb->DataTransferLength);
        // Fill in the INQUIRY data buffer   
        VdiskInquiry((PINQUIRYDATA)InquirySrb->DataBuffer);
        // Return SUCCESS
        InquirySrb->SrbStatus = SRB_STATUS_SUCCESS;
    }
    else
    {
        KdPrint(("VdiskMpInquiry: This target and Lun is empty.\r\n"));
        InquirySrb->SrbStatus = SRB_STATUS_SELECTION_TIMEOUT;
    }
    return InquirySrb->SrbStatus;
}

///////////////////////////////////////////////////////////////////////////////
//
static ULONG VdiskMpNewDevice(PVOID DeviceExtension, PVOID InitializationContext,
	                            PCHAR ArgumentString,
                                PVSP_CONFIGURATION_INFORMATION ConfigInfo,
#ifdef VSPORT_PNP
                                PCM_RESOURCE_LIST AllocatedResources,
                                PCM_RESOURCE_LIST AllocatedResourcesTranslated,
#endif
	                            PBOOLEAN Again)
{
    ULONG i;
    KdPrint(("VdiskMpNewDevice enter...\r\n"));
    // Fill the configuration information values
    ConfigInfo->MaximumTransferLength = 0x10000;
    ConfigInfo->NumberOfBuses = NUMBER_OF_BUSES;
    ConfigInfo->MaximumNumberOfTargets = NUMBER_OF_TARGETS;
#ifdef VSPORT_PNP
    ConfigInfo->PortWmiContext = &VdiskMpWmiAdapter;
    ConfigInfo->LunWmiContext = &VdiskMpWmiLun;
#endif
    // VsPort will call SRB_FUNCTION_SHUTDOWN
    ConfigInfo->CachesData = TRUE;
    // For all buses
    for ( i = 0; i < NUMBER_OF_BUSES; i++ )
        ConfigInfo->InitiatorBusId[i] = INITIATOR_ID;
    // The ONLY device
    *Again = FALSE;
    return SP_RETURN_FOUND;
	UNREFERENCED_PARAMETER(ArgumentString);
	UNREFERENCED_PARAMETER(InitializationContext);
	UNREFERENCED_PARAMETER(DeviceExtension);
#ifdef VSPORT_PNP
	UNREFERENCED_PARAMETER(AllocatedResources);
	UNREFERENCED_PARAMETER(AllocatedResourcesTranslated);
#endif
}

///////////////////////////////////////////////////////////////////////////////
//
static BOOLEAN VdiskMpInitialize(PVOID DeviceExtension)
{
    KdPrint(("VdiskMpInitialize enter... DevExt 0x%X\r\n", DeviceExtension));
    ASSERT(DeviceExtension);
    // Zeror Luns
    RtlZeroMemory( DeviceExtension, sizeof(VDISK_DEVICE_EXTENSION) );
    // Initialize the device extension
    KeInitializeSpinLock(&(((PVDISK_DEVICE_EXTENSION)DeviceExtension)->SpinLock));
    return TRUE;
}

#ifdef VSPORT_PNP
///////////////////////////////////////////////////////////////////////////////
// It calls when SCSI adapter unloaded (See VspDevPnp IRP_MN_QUERY_REMOVE_DEVICE)
// We need to check all LUNs and check leaks
static VOID VdiskMpStopDevice(IN PVOID DeviceExtension)
{
    // device count
    ULONG Index;
    KdPrint(("VdiskMpStopDevice enter...\r\n"));
    ASSERT(DeviceExtension);
    for (Index=0; Index < NUMBER_OF_TARGETS * NUMBER_OF_LUNS; Index++)
        if (((PVDISK_DEVICE_EXTENSION)DeviceExtension)->Luns[Index] != NULL)
        {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -