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

📄 class2.c

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

    if (irp == NULL) {
        ExFreePool(senseInfoBuffer);
        DebugPrint((1, "ScsiClassSendSrbSynchronous: Can't allocate Irp\n"));
        return(STATUS_INSUFFICIENT_RESOURCES);
    }

    //
    // Disable synchronous transfer for these requests.
    //

    Srb->SrbFlags |= SRB_FLAGS_DISABLE_SYNCH_TRANSFER;

    //
    // Set the transfer length.
    //

    Srb->DataTransferLength = BufferLength;

    //
    // Zero out status.
    //

    Srb->ScsiStatus = Srb->SrbStatus = 0;
    Srb->NextSrb = 0;

    //
    // Get next stack location.
    //

    irpStack = IoGetNextIrpStackLocation(irp);

    //
    // Set up SRB for execute scsi request. Save SRB address in next stack
    // for the port driver.
    //

    irpStack->Parameters.Scsi.Srb = Srb;

    //
    // Set up IRP Address.
    //

    Srb->OriginalRequest = irp;

    //
    // Call the port driver with the request and wait for it to complete.
    //

    status = IoCallDriver(deviceExtension->PortDeviceObject, irp);

    if (status == STATUS_PENDING) {
        KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, NULL);
    }

    //
    // Check that request completed without error.
    //

    if (SRB_STATUS(Srb->SrbStatus) != SRB_STATUS_SUCCESS) {

        //
        // Release the queue if it is frozen.
        //

        if (Srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) {
            ScsiClassReleaseQueue(DeviceObject);
        }

        //
        // Update status and determine if request should be retried.
        //

        retry = ScsiClassInterpretSenseInfo(DeviceObject,
                                            Srb,
                                            IRP_MJ_SCSI,
                                            0,
                                            MAXIMUM_RETRIES  - retryCount,
                                            &status);

        if (retry) {

            if ((status == STATUS_DEVICE_NOT_READY && ((PSENSE_DATA) senseInfoBuffer)
                ->AdditionalSenseCode == SCSI_ADSENSE_LUN_NOT_READY) ||
                SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_SELECTION_TIMEOUT) {

                LARGE_INTEGER delay;

                //
                // Delay for 2 seconds.
                //

                delay.QuadPart = (LONGLONG)( - 10 * 1000 * 1000 * 2 );

                //
                // Stall for a while to let the controller spinup.
                //

                KeDelayExecutionThread(KernelMode,
                                       FALSE,
                                       &delay);

            }

            //
            // If retries are not exhausted then retry this operation.
            //

            if (retryCount--) {
                goto retry;
            }
        }

    } else {

        status = STATUS_SUCCESS;
    }

    ExFreePool(senseInfoBuffer);
    return status;

} // end ScsiClassSendSrbSynchronous()


BOOLEAN
STDCALL
ScsiClassInterpretSenseInfo(
    IN PDEVICE_OBJECT DeviceObject,
    IN PSCSI_REQUEST_BLOCK Srb,
    IN UCHAR MajorFunctionCode,
    IN ULONG IoDeviceCode,
    IN ULONG RetryCount,
    OUT NTSTATUS *Status
    )

/*++

Routine Description:

    This routine interprets the data returned from the SCSI
    request sense. It determines the status to return in the
    IRP and whether this request can be retried.

Arguments:

    DeviceObject - Supplies the device object associated with this request.

    Srb - Supplies the scsi request block which failed.

    MajorFunctionCode - Supplies the function code to be used for logging.

    IoDeviceCode - Supplies the device code to be used for logging.

    Status - Returns the status for the request.

Return Value:

    BOOLEAN TRUE: Drivers should retry this request.
            FALSE: Drivers should not retry this request.

--*/

{
    PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
    PDEVICE_EXTENSION physicalExtension = deviceExtension->PhysicalDevice->DeviceExtension;
    PSENSE_DATA       senseBuffer = Srb->SenseInfoBuffer;
    BOOLEAN           retry = TRUE;
    BOOLEAN           logError = FALSE;
    ULONG             badSector = 0;
    ULONG             uniqueId = 0;
    NTSTATUS          logStatus;
    ULONG             readSector;
    ULONG             index;
    PIO_ERROR_LOG_PACKET errorLogEntry;
#if DBG
    ULONG             i;
#endif


    //
    // Check that request sense buffer is valid.
    //

#if DBG
    DebugPrint((3, "Opcode %x\nParameters: ",Srb->Cdb[0]));
    for (i = 1; i < 12; i++) {
        DebugPrint((3,"%x ",Srb->Cdb[i]));
    }
    DebugPrint((3,"\n"));
#endif

    if (Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID &&
        Srb->SenseInfoBufferLength >= FIELD_OFFSET(SENSE_DATA, CommandSpecificInformation)) {

        DebugPrint((1,"ScsiClassInterpretSenseInfo: Error code is %x\n",
                    senseBuffer->ErrorCode));
        DebugPrint((1,"ScsiClassInterpretSenseInfo: Sense key is %x\n",
                    senseBuffer->SenseKey));
        DebugPrint((1, "ScsiClassInterpretSenseInfo: Additional sense code is %x\n",
                    senseBuffer->AdditionalSenseCode));
        DebugPrint((1, "ScsiClassInterpretSenseInfo: Additional sense code qualifier is %x\n",
                  senseBuffer->AdditionalSenseCodeQualifier));

        //
        // Zero the additional sense code and additional sense code qualifier
        // if they were not returned by the device.
        //

        readSector = senseBuffer->AdditionalSenseLength +
            FIELD_OFFSET(SENSE_DATA, AdditionalSenseLength);

        if (readSector > Srb->SenseInfoBufferLength) {
            readSector = Srb->SenseInfoBufferLength;
        }

        if (readSector <= FIELD_OFFSET(SENSE_DATA, AdditionalSenseCode)) {
            senseBuffer->AdditionalSenseCode = 0;
        }

        if (readSector <= FIELD_OFFSET(SENSE_DATA, AdditionalSenseCodeQualifier)) {
            senseBuffer->AdditionalSenseCodeQualifier = 0;
        }

        switch (senseBuffer->SenseKey & 0xf) {

        case SCSI_SENSE_NOT_READY:

            DebugPrint((1,"ScsiClassInterpretSenseInfo: Device not ready\n"));
            *Status = STATUS_DEVICE_NOT_READY;

            switch (senseBuffer->AdditionalSenseCode) {

            case SCSI_ADSENSE_LUN_NOT_READY:

                DebugPrint((1,"ScsiClassInterpretSenseInfo: Lun not ready\n"));

                switch (senseBuffer->AdditionalSenseCodeQualifier) {

                case SCSI_SENSEQ_BECOMING_READY:

                    DebugPrint((1, "ScsiClassInterpretSenseInfo:"
                                " In process of becoming ready\n"));
                    break;

                case SCSI_SENSEQ_MANUAL_INTERVENTION_REQUIRED:

                    DebugPrint((1, "ScsiClassInterpretSenseInfo:"
                                " Manual intervention required\n"));
                    *Status = STATUS_NO_MEDIA_IN_DEVICE;
                    retry = FALSE;
                    break;

                case SCSI_SENSEQ_FORMAT_IN_PROGRESS:

                    DebugPrint((1, "ScsiClassInterpretSenseInfo: Format in progress\n"));
                    retry = FALSE;
                    break;

                case SCSI_SENSEQ_INIT_COMMAND_REQUIRED:

                default:

                    DebugPrint((1, "ScsiClassInterpretSenseInfo:"
                                " Initializing command required\n"));

                    //
                    // This sense code/additional sense code
                    // combination may indicate that the device
                    // needs to be started.  Send an start unit if this
                    // is a disk device.
                    //

                    if (deviceExtension->DeviceFlags & DEV_SAFE_START_UNIT) {
                        StartUnit(DeviceObject);
                    }

                    break;

                } // end switch (senseBuffer->AdditionalSenseCodeQualifier)

                break;

            case SCSI_ADSENSE_NO_MEDIA_IN_DEVICE:

                DebugPrint((1,
                            "ScsiClassInterpretSenseInfo:"
                            " No Media in device.\n"));
                *Status = STATUS_NO_MEDIA_IN_DEVICE;
                retry = FALSE;

                //
                // signal autorun that there isn't any media in the device
                //

                if((deviceExtension->MediaChangeEvent != NULL)&&
                   (!deviceExtension->MediaChangeNoMedia)) {
                    KeSetEvent(deviceExtension->MediaChangeEvent,
                           (KPRIORITY) 0,
                           FALSE);
                    DebugPrint((0, "ScsiClassInterpretSenseInfo:"
                                   "Detected No Media In Device "
                                   "[irp = 0x%lx]\n", Srb->OriginalRequest));
                    deviceExtension->MediaChangeNoMedia = TRUE;
                }

                break;
            } // end switch (senseBuffer->AdditionalSenseCode)

            break;

        case SCSI_SENSE_DATA_PROTECT:

            DebugPrint((1, "ScsiClassInterpretSenseInfo: Media write protected\n"));
            *Status = STATUS_MEDIA_WRITE_PROTECTED;
            retry = FALSE;
            break;

        case SCSI_SENSE_MEDIUM_ERROR:

            DebugPrint((1,"ScsiClassInterpretSenseInfo: Bad media\n"));
            *Status = STATUS_DEVICE_DATA_ERROR;

            retry = FALSE;
            logError = TRUE;
            uniqueId = 256;
            logStatus = 0;//IO_ERR_BAD_BLOCK;
            break;

        case SCSI_SENSE_HARDWARE_ERROR:

            DebugPrint((1,"ScsiClassInterpretSenseInfo: Hardware error\n"));
            *Status = STATUS_IO_DEVICE_ERROR;

            logError = TRUE;
            uniqueId = 257;
            logStatus = 0;//IO_ERR_CONTROLLER_ERROR;

            break;

        case SCSI_SENSE_ILLEGAL_REQUEST:

            DebugPrint((1, "ScsiClassInterpretSenseInfo: Illegal SCSI request\n"));
            *Status = STATUS_INVALID_DEVICE_REQUEST;

            switch (senseBuffer->AdditionalSenseCode) {

            case SCSI_ADSENSE_ILLEGAL_COMMAND:
                DebugPrint((1, "ScsiClassInterpretSenseInfo: Illegal command\n"));
                retry = FALSE;
                break;

            case SCSI_ADSENSE_ILLEGAL_BLOCK:
                DebugPrint((1, "ScsiClassInterpretSenseInfo: Illegal block address\n"));
                *Status = STATUS_NONEXISTENT_SECTOR;
                retry = FALSE;
                break;

            case SCSI_ADSENSE_INVALID_LUN:
                DebugPrint((1,"ScsiClassInterpretSenseInfo: Invalid LUN\n"));
                *Status = STATUS_NO_SUCH_DEVICE;
                retry = FALSE;
                break;

            case SCSI_ADSENSE_MUSIC_AREA:
                DebugPrint((1,"ScsiClassInterpretSenseInfo: Music area\n"));
                retry = FALSE;
                break;

            case SCSI_ADSENSE_DATA_AREA:
                DebugPrint((1,"ScsiClassInterpretSenseInfo: Data area\n"));
                retry = FALSE;
                break;

            case SCSI_ADSENSE_VOLUME_OVERFLOW:
                DebugPrint((1, "ScsiClassInterpretSenseInfo: Volume overflow\n"));
                retry = FALSE;
                break;

            case SCSI_ADSENSE_INVALID_CDB:
                DebugPrint((1, "ScsiClassInterpretSenseInfo: Invalid CDB\n"));

                //
                // Check if write cache enabled.
                //

                if (deviceExtension->DeviceFlags & DEV_WRITE_CACHE) {

                    //
                    // Assume FUA is not supported.
                    //

                    deviceExtension->DeviceFlags &= ~DEV_WRITE_CACHE;
                    retry = TRUE;

                } else {
                    retry = FALSE;
                }

                break;

            } // end switch (senseBuffer->AdditionalSenseCode)

            break;

        case SCSI_SENSE_UNIT_ATTENTION:

            switch (senseBuffer->AdditionalSenseCode) {
            case SCSI_ADSENSE_MEDIUM_CHANGED:
                DebugPrint((1, "ScsiClassInterpretSenseInfo: Media changed\n"));

                if(deviceExtension->MediaChangeEvent != NULL) {

                    KeSetEvent(deviceExtension->MediaChangeEvent,
                           (KPRIORITY) 0,
                           FALSE);
                    DebugPrint((0, "ScsiClassInterpretSenseInfo:"
                                   "New Media Found - Setting MediaChanged event"
                                   " [irp = 0x%lx]\n", Srb->OriginalRequest));
                    deviceExtension->MediaChangeNoMedia = FALSE;

                }
                break;

            case SCSI_ADSENSE_BUS_RESET:
                DebugPrint((1,"ScsiClassInterpretSenseInfo: Bus reset\n"));
                break;

            default:
                DebugPrint((1,"ScsiClassInterpretSenseInfo: Unit attention\n"));
                break;

            } // end  switch (senseBuffer->AdditionalSenseCode)

            if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA &&
                DeviceObject->Vpb->Flags & VPB_MOUNTED) {

                //
                // Set bit to indicate that media may have changed
                // and volume needs verification.
                //

                DeviceObject->Flags |= DO_VERIFY_VOLUME;

                *Status = STATUS_VERIFY_REQUIRED;
                retry = FALSE;

            } else {

                *Status = STATUS_IO_DEVICE_ERROR;

            }

            //
            // A media change may have occured so increment the change
            // count for the physical device
            //

            physicalExtension->MediaChangeCount++;

            DebugPrint((2, "ScsiClassInterpretSenseInfo - Media change "
                           "count for device %d is %d\n",
                        physicalExtension->DeviceNumber,
                        physicalExtension->MediaChangeCount));

            break;

        case SCSI_SENSE_ABORTED_COMMAND:

            DebugPrint((1,"ScsiClassInterpretSenseInfo: Command aborted\n"));
            *Status = STATUS_IO_DEVICE_ERROR;
            break;

        case SCSI_SENSE_RECOVERED_ERROR:

            DebugPrint((1,"ScsiClassInterpretSenseInfo: Recovered error\n"));
            *Status = STATUS_SUCCESS;
            retry = FALSE;
           

⌨️ 快捷键说明

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