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

📄 cdrom.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 5 页
字号:

    deviceExtension->PhysicalDevice = deviceObject;

    //
    // Initialize lock count to zero. The lock count is used to
    // disable the ejection mechanism when media is mounted.
    //

    deviceExtension->LockCount = 0;

    //
    // Save system cdrom number
    //

    deviceExtension->DeviceNumber = *DeviceCount;

    //
    // Copy port device object to device extension.
    //

    deviceExtension->PortDeviceObject = PortDeviceObject;

    //
    // Set the alignment requirements for the device based on the
    // host adapter requirements
    //

    if (PortDeviceObject->AlignmentRequirement > deviceObject->AlignmentRequirement) {
        deviceObject->AlignmentRequirement = PortDeviceObject->AlignmentRequirement;
    }

    //
    // Save address of port driver capabilities.
    //

    deviceExtension->PortCapabilities = PortCapabilities;

    //
    // Clear SRB flags.
    //

    deviceExtension->SrbFlags = 0;
    deviceExtension->SrbFlags |= SRB_FLAGS_DISABLE_SYNCH_TRANSFER;

    //
    // Allocate request sense buffer.
    //

    senseData = ExAllocatePool(NonPagedPoolCacheAligned, SENSE_BUFFER_SIZE);

    if (senseData == NULL) {

        //
        // The buffer cannot be allocated.
        //

        status = STATUS_INSUFFICIENT_RESOURCES;
        goto CreateCdRomDeviceObjectExit;
    }

    //
    // Set the sense data pointer in the device extension.
    //

    deviceExtension->SenseData = senseData;

    //
    // CDROMs are not partitionable so starting offset is 0.
    //

    deviceExtension->StartingOffset.LowPart = 0;
    deviceExtension->StartingOffset.HighPart = 0;

    //
    // Path/TargetId/LUN describes a device location on the SCSI bus.
    // This information comes from the LunInfo buffer.
    //

    deviceExtension->PortNumber = (UCHAR)PortNumber;
    deviceExtension->PathId = LunInfo->PathId;
    deviceExtension->TargetId = LunInfo->TargetId;
    deviceExtension->Lun = LunInfo->Lun;

    //
    // Set timeout value in seconds.
    //

    timeOut = ScsiClassQueryTimeOutRegistryValue(RegistryPath);
    if (timeOut) {
        deviceExtension->TimeOutValue = timeOut;
    } else {
        deviceExtension->TimeOutValue = SCSI_CDROM_TIMEOUT;
    }

    //
    // Build the lookaside list for srb's for the physical disk. Should only
    // need a couple.
    //

    ScsiClassInitializeSrbLookasideList(deviceExtension,
                                        CDROM_SRB_LIST_SIZE);

    srbListInitialized = TRUE;

    //
    // Back pointer to device object.
    //

    deviceExtension->DeviceObject = deviceObject;

    //
    // Allocate buffer for drive geometry.
    //

    deviceExtension->DiskGeometry =
        ExAllocatePool(NonPagedPool, sizeof(DISK_GEOMETRY));

    if (deviceExtension->DiskGeometry == NULL) {

        status = STATUS_INSUFFICIENT_RESOURCES;
        goto CreateCdRomDeviceObjectExit;
    }

    //
    // Set up media change support defaults.
    //

    cddata = (PCDROM_DATA)(deviceExtension + 1);

    KeInitializeSpinLock(&cddata->FormSpinLock);
    KeInitializeSpinLock(&cddata->TimerIrpSpinLock);
    InitializeListHead(&cddata->TimerIrpList);

    cddata->MediaChangeCountDown = MEDIA_CHANGE_DEFAULT_TIME;
    cddata->MediaChangeSupported = FALSE;
    cddata->MediaChange = FALSE;

    //
    // Assume that there is initially no media in the device
    // only notify upper layers if there is something there
    //

    deviceExtension->MediaChangeNoMedia = TRUE;
    cddata->MediaChangeIrp = NULL;
#ifdef DBG
    cddata->MediaChangeIrpTimeInUse = 0;
    cddata->MediaChangeIrpLost = FALSE;
#endif

    //
    // Scan for Scsi controllers that require special processing.
    //

    ScanForSpecial(deviceObject,
                   (PINQUIRYDATA) LunInfo->InquiryData,
                   PortCapabilities);

    //
    // Do READ CAPACITY. This SCSI command
    // returns the last sector address on the device
    // and the bytes per sector.
    // These are used to calculate the drive capacity
    // in bytes.
    //

    status = ScsiClassReadDriveCapacity(deviceObject);
    bps = deviceExtension->DiskGeometry->BytesPerSector;

    if (!NT_SUCCESS(status) || !bps) {

        DebugPrint((1,
                "CreateCdRomDeviceObjects: Can't read capacity for device %s\n",
                ntNameBuffer));

        //
        // Set disk geometry to default values (per ISO 9660).
        //

        bps = 2048;
        deviceExtension->SectorShift = 11;
        deviceExtension->PartitionLength.QuadPart = (LONGLONG)(0x7fffffff);
    } else {

        //
        // Insure that bytes per sector is a power of 2
        // This corrects a problem with the HP 4020i CDR where it
        // returns an incorrect number for bytes per sector.
        //

        lastBit = (ULONG) -1;
        while (bps) {
            lastBit++;
            bps = bps >> 1;
        }

        bps = 1 << lastBit;
    }
    deviceExtension->DiskGeometry->BytesPerSector = bps;
    DebugPrint((2, "CreateCdRomDeviceObject: Calc'd bps = %x\n", bps));

    //
    // Check to see if this is some sort of changer device
    //

    changerDevice = FALSE;

    //
    // Search for devices that have special requirements for media
    // change support.
    //

    if (deviceExtension->Lun > 0) {
        changerDevice = TRUE;
    }

    if (!changerDevice) {
        changerDevice = IsThisASanyo(deviceObject, deviceExtension->PathId,
                                     deviceExtension->TargetId);
    }

    if (!changerDevice) {
        ULONG tmp;
        changerDevice = IsThisAnAtapiChanger(deviceObject, &tmp);
    }

    if (!changerDevice) {
        changerDevice = IsThisAMultiLunDevice(deviceObject, PortDeviceObject);
    }

    //
    // If it is a changer device, increment the timeout to take platter-swapping
    // time into account
    //

    if(changerDevice) {
        deviceExtension->TimeOutValue += SCSI_CHANGER_BONUS_TIMEOUT;
    }

    //
    // Create the media change named event.  If this succeeds then continue
    // initializing the media change support data items.
    //

    CdRomCreateNamedEvent(deviceExtension,*DeviceCount);
    if (deviceExtension->MediaChangeEvent) {

        //
        // If this is not a changer, get an IRP for the timer request
        // and initialize the timer.
        //

        if (!changerDevice) {

            //
            // Not a changer device - continue with media change initialization.
            // Determine if the user actually wants media change events.
            //

            if (CdRomCheckRegistryForMediaChangeValue(RegistryPath, *DeviceCount)) {
                PIO_STACK_LOCATION irpStack;
                PSCSI_REQUEST_BLOCK srb;
                PIRP irp;

                //
                // User wants it - preallocate IRP and SRB.
                //

                irp = IoAllocateIrp((CCHAR)(deviceObject->StackSize+1),
                                    FALSE);
                if (irp) {
                    PVOID buffer;

                    srb = ExAllocatePool(NonPagedPool, sizeof(SCSI_REQUEST_BLOCK));
                    buffer = ExAllocatePool(NonPagedPoolCacheAligned, SENSE_BUFFER_SIZE);

                    if (srb && buffer) {
                        PCDB cdb;

                        //
                        // All resources have been allocated set up the IRP.
                        //

                        IoSetNextIrpStackLocation(irp);
                        irpStack = IoGetCurrentIrpStackLocation(irp);
                        irpStack->DeviceObject = deviceObject;
                        irpStack = IoGetNextIrpStackLocation(irp);
                        cddata->MediaChangeIrp = irp;
                        irpStack->Parameters.Scsi.Srb = srb;

                        //
                        // Initialize the SRB
                        //

                        RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK));

                        srb->CdbLength = 6;
                        srb->TimeOutValue = deviceExtension->TimeOutValue * 2;
                        srb->QueueTag = SP_UNTAGGED;
                        srb->QueueAction = SRB_SIMPLE_TAG_REQUEST;
                        srb->Length = SCSI_REQUEST_BLOCK_SIZE;
                        srb->PathId = deviceExtension->PathId;
                        srb->TargetId = deviceExtension->TargetId;
                        srb->Lun = deviceExtension->Lun;
                        srb->Function = SRB_FUNCTION_EXECUTE_SCSI;

                        //
                        // Initialize and set up the sense information buffer
                        //

                        RtlZeroMemory(buffer, SENSE_BUFFER_SIZE);
                        srb->SenseInfoBuffer = buffer;
                        srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE;

                        //
                        // Initialize the CDB
                        //

                        cdb = (PCDB)&srb->Cdb[0];
                        cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY;
                        cdb->CDB6GENERIC.LogicalUnitNumber = deviceExtension->Lun;

                        //
                        // It is ok to support media change events on this device.
                        //

                        cddata->MediaChangeSupported = TRUE;
                        cddata->MediaChange = TRUE;

                    } else {

                        if (srb) {
                            ExFreePool(srb);
                        }
                        if (buffer) {
                            ExFreePool(buffer);
                        }
                        IoFreeIrp(irp);
                    }
                }
            } else {
                deviceExtension->MediaChangeEvent = NULL;
            }
        } else {
            deviceExtension->MediaChangeEvent = NULL;
        }
    }

    //
    // Assume use of 6-byte mode sense/select for now.
    //

    cddata->XAFlags |= XA_USE_6_BYTE;

    //
    // Build and issue mode sense with Read error recovery page. This will be used to change
    // block size in case of any raw reads (Mode 2, Form 2).
    //

    length = (sizeof(MODE_READ_RECOVERY_PAGE) + MODE_BLOCK_DESC_LENGTH + MODE_HEADER_LENGTH);

    RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK));

    srb.CdbLength = 6;
    cdb = (PCDB)srb.Cdb;

    //
    // Set timeout value from device extension.
    //

    srb.TimeOutValue = deviceExtension->TimeOutValue;

    //
    // Build the MODE SENSE CDB. The data returned will be kept in the device extension
    // and used to set block size.
    //

    cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
    cdb->MODE_SENSE.PageCode = 0x1;
    cdb->MODE_SENSE.AllocationLength = (UCHAR)length;

    buffer = ExAllocatePool(NonPagedPoolCacheAligned, (sizeof(MODE_READ_RECOVERY_PAGE) + MODE_BLOCK_DESC_LENGTH + MODE_HEADER_LENGTH10));
    if (!buffer) {
        status = STATUS_INSUFFICIENT_RESOURCES;
        goto CreateCdRomDeviceObjectExit;
    }

    status = ScsiClassSendSrbSynchronous(deviceObject,
                                         &srb,
                                         buffer,
                                         length,
                                         FALSE);
    if (!NT_SUCCESS(status)) {

        //
        // May be Atapi, try 10-byte.
        //

        length = (sizeof(MODE_READ_RECOVERY_PAGE) + MODE_BLOCK_DESC_LENGTH + MODE_HEADER_LENGTH10);

        RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK));

        //
        // Build the MODE SENSE CDB.
        //

        srb.CdbLength = 10;
        cdb = (PCDB)srb.Cdb;

        //
        // Set timeout value from device extension.
        //

        srb.TimeOutValue = deviceExtension->TimeOutValue;

        cdb->MODE_SENSE10.OperationCode = SCSIOP_MODE_SENSE10;
        cdb->MODE_SENSE10.PageCode = 0x1;

        cdb->MODE_SENSE10.AllocationLength[0] = (UCHAR)(length >> 8);
        cdb->MODE_SENSE10.AllocationLength[1] = (UCHAR)(length & 0xFF);

        status = ScsiClassSendSrbSynchronous(deviceObject,
                                             &srb,

⌨️ 快捷键说明

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