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

📄 ide.c

📁 硬盘驱动的例子
💻 C
📖 第 1 页 / 共 4 页
字号:
            // check the controller status
            //
            if (controllerStatus & ERROR_STATUS) {

#if DBG
                DbgPrint("IdeDPC: Error for RESET_DRIVER_RECALIBRATION - controllerStatus %x\n",controllerStatus);
#endif

                goto RetryIrp;

            }

            //
            // if we have an irp, then we need to restart the packet
            //
#if DBG
            DbgPrint("IdeDPC: Recalibrating drive : IRP %x\n",irp); 
#endif

            //
            // If the disk operation was a verify then don't retry.
            //
            if ((devExt->IrpRetryCount < MAXIMUM_IRP_RETRY_COUNT) &&
                (ioStack->MajorFunction != IRP_MJ_DEVICE_CONTROL))  {

                devExt->PacketIsBeingRetried = TRUE;

                //
                // Let the disk catch its breath
                //
                KeStallExecutionProcessor(25);

                //
                // and let's try that again
                //
                IdeStartIo(deviceObject, irp);

            } else {

                //
                // We've retried too many times.  Finish the irp with 
                // failure and return.
                //
#if DBG
                DbgPrint( "IdeDPC: too many retries 1; will fail IRP\n");
#endif

                FinishIrp(devExt, STATUS_DISK_RECALIBRATE_FAILED);

            }

            //
            // clear the reset status and return
            //
            devExt->ControllerData->ResettingController = RESET_NOT_RESETTING;

            return;

    }

    //
    // We're not resetting
    //
    // Note that for READ and WRITE operations, if the operation did NOT
    // not complete, that fact will be caught later in the code and some
    // attempts at corrective action will take place.
    //
    if (devExt->OperationType == IRP_MJ_READ)  {

        PVOID BufferToReadTo;
        BOOLEAN CheckDrq = FALSE;

#if DBG
        DbgPrint("IdeDPC: IRP_MJ_READ - RemainingTransferLength %x\n",
                        devExt->RemainingTransferLength);
#endif

        //
        // Make sure that since the IO is complete, the DRQ is low
        // So, first let's wait until the controller is ready.
        //
        ntStatus = STATUS_SUCCESS;

        //
        // If the controller is busy, wait for it to become ready...
        //
        if (READ_PORT_UCHAR(controllerData->ControllerAddress + STATUS_REGISTER) &
                        BUSY_STATUS)  {

#if DBG
            DbgPrint("Extra wait -- READ\n");
#endif

            ntStatus = IdeWaitControllerReady(controllerData, 10, 5000);
        }

        //
        // Did the controller become ready?
        //
        if (NT_SUCCESS(ntStatus))  {

            //
            // We're not in a data request phase, right?
            //
            if (READ_PORT_UCHAR(
                    controllerData->ControllerAddress + STATUS_REGISTER) &
                                    DATA_REQUEST_STATUS) {

                //
                // Data request is ASSERTED?  We must have a problem...
                //
#if DBG
                DbgPrint("IdeDPC: READ data overrun - controller status %x\n",
                                        controllerStatus);
#endif

                controllerStatus |= ERROR_STATUS;

                goto RetryIrp;
            }

        } else {

            //
            // Error reading the controller.  Bummer city.
            //
#if DBG
            DbgPrint("IdeDPC: IdeWaitControllerReady failure during READ\n");
#endif

            controllerStatus |= ERROR_STATUS;

            goto RetryIrp;
        }

    } else  {

        //
        // The operation wasn't a READ, so it BETTER be a WRITE
        //
        ASSERT(devExt->OperationType == IRP_MJ_WRITE);

        //
        // Make sure the controller is happy
        //
#if DBG
        DbgPrint("IdeDPC: IRP_MJ_WRITE - RemainingTransferLength %x\n",
                    devExt->RemainingTransferLength);
#endif


#if DBG
        DbgPrint("Extra wait -- WRITE\n");
#endif

        //
        // Make sure that since the IO is complete, the DRQ is low
        // So, first let's wait until the controller is ready.
        //
        ntStatus = STATUS_SUCCESS;

        //
        // If the controller is busy, wait for it to become ready...
        //
        if (READ_PORT_UCHAR(controllerData->ControllerAddress + STATUS_REGISTER) &
                        BUSY_STATUS)  {

#if DBG
            DbgPrint("Extra wait -- WRITE\n");
#endif

            ntStatus = IdeWaitControllerReady(controllerData, 10, 5000);
        }

        //
        // Did the controller become ready?
        //
        if (NT_SUCCESS(ntStatus))  {

            //
            // Is DRQ low?
            //
            if (READ_PORT_UCHAR(controllerData->ControllerAddress + STATUS_REGISTER) &
                                        DATA_REQUEST_STATUS) {

                //
                // not low => we must have a problem
                //

#if DBG
                DbgPrint("IdeDPC: WRITE data overrun - controller status %x\n",
                            controllerStatus);
#endif

                    controllerStatus |= ERROR_STATUS;

                goto RetryIrp;

            }

        } else {


            //
            // error reading the controller.  Bummer city.
            //
#if DBG
            DbgPrint("IdeDPC: IdeWaitControllerReady failure during WRITE\n");
#endif

            controllerStatus |= ERROR_STATUS;

            goto RetryIrp;

        }

    }



    //
    // If there was a correctable error, let us know, but we can continue.
    //
    if (controllerStatus & CORRECTED_ERROR_STATUS) {

#if DBG
        DbgPrint("IdeDPC: CORRECTABLE ERROR - Continuing Operation\n");
#endif

    }

RetryIrp:

    //
    // does the controller have a problem?
    //
    if (controllerStatus & ERROR_STATUS) {

        //
        // inform us that we're going to try and recover this irp
        //
#if DBG
        DbgPrint("IdeDPC: IRP recovery: Irp %x - retry %d more times\n",
                    irp,
                    MAXIMUM_IRP_RETRY_COUNT - devExt->IrpRetryCount);
#endif

        //
        // Check if we're exceeded the IRP retry count
        //
        if (devExt->IrpRetryCount < MAXIMUM_IRP_RETRY_COUNT)  {

            //
            // We haven't exceeded our count, so let's reset the disk.
            // Since this will cause an interrupt, we can't do
            // anything more in the DPC, so we just return
            //
            KeSynchronizeExecution(controllerData->InterruptObject,
                            ResetDisk,
                            devExt);

            return;

        } else {

            //
            // Too many retries, so fail the IRP
            //
#if DBG
            DbgPrint("IdeDPC: Disk Controller still fails after %d retries - FAILING operation\n",MAXIMUM_IRP_RETRY_COUNT);
#endif

            returnStatus = STATUS_DISK_OPERATION_FAILED;

        }

    }

    //
    // Now, test for the success/failure of the operation.
    //
    if (NT_SUCCESS(returnStatus) && devExt->RemainingTransferLength == 0) {

        //
        // Success (complete transfer of data).  Let the requestor know.
        //
        returnStatus = STATUS_SUCCESS;

        irp->IoStatus.Information = ioStack->Parameters.Read.Length;

    } else {

        //
        // An error.  Bummer. Oh well...
        //
        // I'm thinkin' we're not big on error recovery in this driver...
        //
        irp->IoStatus.Status =  STATUS_DISK_OPERATION_FAILED;

        irp->IoStatus.Information = 0;

#if DBG
        DbgPrint("IdeDPC: Irp %x fails, status %x info %x\n",
                    irp->IoStatus.Information);
#endif

    }

    //
    // Complete this IRP and call IoStartNextPacketByKey
    //
    FinishIrp(devExt, returnStatus);

}



///////////////////////////////////////////////////////////////////////////////
//
//  FinishIrp
//
//    This routine will request to start the next transaction and
//    complete the current IRP.
//
//  INPUTS:
//
//    devExt          - disk information
//    completionStatus  - status to complete the IRP with
//
//  OUTPUTS:
//  
//    None.
//
//  RETURNS:
//
//    None
//
//      IRQL:
//
//    IRQL_DISPATCH_LEVEL
//
//  NOTES:
//
///////////////////////////////////////////////////////////////////////////////
static VOID
FinishIrp(IN PIDE_DEV_EXT devExt,
          IN NTSTATUS NtStatus)
{
    PIRP irp = devExt->DeviceObject->CurrentIrp;

    //
    // For completing read requests we need to flush the I/O buffers.
    //
    if (IoGetCurrentIrpStackLocation(irp)->MajorFunction == IRP_MJ_READ) {

        KeFlushIoBuffers(irp->MdlAddress, TRUE, FALSE);
    }

    //
    // Start the next packet by keep... Next sector first scan to try to keep
    // the heads moving forward!  Such an optimization...
    //
    IoStartNextPacketByKey(devExt->DeviceObject,
                            FALSE,
                            devExt->FirstSectorOfRequest);

    irp->IoStatus.Status = NtStatus;

#if DBG
    DbgPrint("FinishIrp: Finishing Request of Irp: %x\n", irp); 
#endif

    IoCompleteRequest(irp, IO_DISK_INCREMENT);
}






///////////////////////////////////////////////////////////////////////////////
//
//  ResetDisk
//
//    This routine will reset the disk
//
//  INPUTS:
//
//    Context           - really, the devExt
//
//  OUTPUTS:
//  
//    None.
//
//  RETURNS:
//
//    FALSE, every time, all the time
//
//      IRQL:
//
//    DIRQL
//
//  NOTES:
//
//    Has to be called at DIRQL to access the registers and protect against
//    other outstanding interrupts generated by outstanding requests
//
///////////////////////////////////////////////////////////////////////////////
static BOOLEAN
ResetDisk(PVOID Context)
{

    PIDE_DEV_EXT devExt = Context;
    PCONTROLLER_DATA controllerData = devExt->ControllerData;

    //
    // Let it Be Known that we are resetting the controller.
    //

#if DBG
    DbgPrint("ResetDisk: Starting reset with failing extension: %x\n",devExt);
#endif

    controllerData->ResettingController = RESET_DRIVE_SET;

    //
    // Reset the controller, since its state isn't what we expect.
    // Wait up to 2 seconds between writes to the control port.
    // Normally we don't like to wait at DIRQL, but this won't generate
    // an interrupt and 10us isn't so bad.
    //

    WRITE_PORT_UCHAR(controllerData->ControlPortAddress,
                RESET_CONTROLLER);

    IdeWaitControllerBusy(controllerData->ControllerAddress + STATUS_REGISTER,
                    20,
                    75000);

    WRITE_PORT_UCHAR(controllerData->ControlPortAddress,
                    (UCHAR)(ENABLE_INTERRUPTS | controllerData->ControlFlags));

    //
    // Every controller reset must be followed by setting the drive
    // parameters of all attached drives.  This DOES cause an
    // interrupt.
    //
    controllerData->InterruptRequiresDpc = TRUE;

    //
    // Before we write to the controller, wait until we're sure it's
    // not still busy setting itself up.  We don't like waiting here,
    // but there's no interrupt to wait on, the wait should be very
    // short, and this code is only executed if the hardware gets
    // messed up.  If it's not ready after 3 seconds, just blast ahead...
    // the operation won't work, but it will time out and be handled
    // later.  Note that we ordinarily don't want to wait this long
    // in a driver, but we don't wait longer than we have to and we
    // may just have to.  This isn't an ordinary event.
    //
    (VOID) IdeWaitControllerReady(controllerData, 20, 150000);

    WRITE_PORT_UCHAR(controllerData->ControllerAddress + DRIVE_HEAD_REGISTER,
        (UCHAR)(devExt->DeviceUnit | (devExt->TracksPerCylinder - 1)));

    WRITE_PORT_UCHAR((controllerData->ControllerAddress + SECTOR_COUNT_REGISTER),
        (UCHAR)(devExt->SectorsPerTrack));

    WRITE_PORT_UCHAR(controllerData->ControllerAddress + COMMAND_REGISTER,
        SET_DRIVE_PARAMETERS_COMMAND);

    //
    // When the interrupt comes, the DPC will see ResettingController
    // and restarting any packets that were in progress.
    //
    return(FALSE);
}

⌨️ 快捷键说明

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