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

📄 ide.c

📁 硬盘驱动的例子
💻 C
📖 第 1 页 / 共 4 页
字号:

                        //
                        // And set the Status and Infomration fields
                        //
                        Irp->IoStatus.Information = tempSize;
                        Irp->IoStatus.Status = STATUS_SUCCESS;

                    }

                    //
                    // Free the buffer holding the partition table information
                    // allocated by IoReadPartitionTable()
                    //
                    ExFreePool(partitionList);
                }
            }

            break ;

        //
        // Update the disk with new partition information.
        //
        case IOCTL_DISK_SET_DRIVE_LAYOUT: 

            //
            // For this sample, we assume a single partition and no
            // alterations... Sorry!
            //
#if DBG
            DbgPrint("IdeDispatchDeviceControl: IOCTL_DISK_SET_DRIVE_LAYOUT unsupported\n");
#endif
            Irp->IoStatus.Information = 0;

            Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;

            break;


        //
        // Is this disk writable?
        //
        case IOCTL_DISK_IS_WRITABLE:

            //
            // SURE it is!
            //
            Irp->IoStatus.Information = 0;

            Irp->IoStatus.Status = STATUS_SUCCESS;
            break;

        //
        // Here's another request that class driver's get.
        // Is the media removable from this device?
        //
        case IOCTL_DISK_MEDIA_REMOVAL:

            //
            // No, it is not.
            //
            Irp->IoStatus.Information = 0;

            Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
            break;


        default: 

            //
            // The supplied operation is not supported by this driver
            //
#if DBG
            DbgPrint("IdeDispatchDeviceControl: Unrecognized IOCTL %x\n",
                    ioStack->Parameters.DeviceIoControl.IoControlCode);
#endif
            Irp->IoStatus.Information = 0;
            Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
            break;

    }

    //
    // Finish up and complete the IRP
    //
    ntStatus = Irp->IoStatus.Status;

    IoCompleteRequest(Irp, IO_NO_INCREMENT);

    return(ntStatus);
}



///////////////////////////////////////////////////////////////////////////////
//
//  IdeDispatchReadWrite
//
//  This is the dispatch entry point for IRP_MJ_READ and IRP_MJ_WRITE requests.
//  All we do here is validate the IRP, and if it's valid mark it pending
//  and call IoStartPacket() to start the request on the device.
//
//
//  INPUTS:
//
//    DeviceObject      - pointer to our device object
//    Irp               - pointer to the IRP
//
//  OUTPUTS:
//  
//    None.
//
//  RETURNS:
//
//    STATUS_PENDING, otherwise STATUS_INVALID_PARAMETER
//
//      IRQL:
//
//    IRQL_PASSIVE_LEVEL
//
//  NOTES:
//
//
///////////////////////////////////////////////////////////////////////////////
NTSTATUS
IdeDispatchReadWrite(IN PDEVICE_OBJECT DeviceObject,
                     IN OUT PIRP Irp)
{
    PPARTITION_DATA partitionData = (PPARTITION_DATA)DeviceObject->DeviceExtension;
    PIDE_DEV_EXT devExt = partitionData->Partition0;
    PIO_STACK_LOCATION ioStack;
    ULONG firstSectorOfRequest;
    LONGLONG byteOffset;
    LONGLONG partitionLength;
    ULONG transferLength;

    partitionLength = partitionData->Pi.PartitionLength.QuadPart;

    //
    // Get a pointer to the current I/O stack location
    //
    ioStack = IoGetCurrentIrpStackLocation(Irp);

    //
    // Pick up some handy parameters from the current I/O Stack.
    // NOTE that although we access the parameters from the READ union,
    // we could be processing EITHER a READ or a WRITE operation. The parameters
    // are at the same locations in both I/O Stacks.
    //
    byteOffset = ioStack->Parameters.Read.ByteOffset.QuadPart;
    transferLength = ioStack->Parameters.Read.Length;

    //
    // Validate the IRP
    //
    // Here we check to see if the parameters are valid with respect to the
    // device.  Specifically:
    //
    //      - The transfer size must not be zero.
    //      - The transfer size must not be > MAXIMUM_TRANSFER_LENGTH bytes
    //      - The transfer must be entirely within one disk partition
    //      - The transfer size must be an even multiple of the sector size
    //
    if ((transferLength == 0) ||
        (transferLength > MAXIMUM_TRANSFER_LENGTH) ||
        ((byteOffset + transferLength) > partitionLength) ||
        (transferLength % devExt->BytesPerSector)) {

        //
        // One of the parameters is not valid
        //
        Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
        Irp->IoStatus.Information = 0;

#if DBG
        DbgPrint("DispatchReadWrite: Invalid Parameter!\n");
        DbgPrint("Major Func = 0x%0x\n", ioStack->MajorFunction);
        DbgPrint("\t\tLength = %d.\n", transferLength);
        DbgPrint("\t\tPartition Length = %d.\n", partitionLength);
#endif

        IoCompleteRequest(Irp, IO_NO_INCREMENT);

        return(STATUS_INVALID_PARAMETER);
    }

    //
    // The IRP is valid.  We will therefore be returning with the IRP
    // pending.
    //
    IoMarkIrpPending(Irp);

    //
    // Convert the partition-relative request to one relative to the
    // start of the disk, and store it back in the IRP for later use.
    //
    byteOffset += partitionData->Pi.StartingOffset.QuadPart;
    ioStack->Parameters.Read.ByteOffset.QuadPart = byteOffset;

    //
    // Determine the sector at which the request starts
    //
    firstSectorOfRequest = (ULONG)(byteOffset >> devExt->ByteShiftToSector);

    //
    // Attempt to start the request.
    //
    // NOTE that we sort the queue of IRPs based on the starting sector
    // of the request.  Since requests are processed quickly on the disk,
    // we do not make them cancellable.
    //
    IoStartPacket(devExt->DeviceObject,
                  Irp,
                  &firstSectorOfRequest,
                  NULL);

    //
    // Return with the request queued
    //
    return(STATUS_PENDING);
}


///////////////////////////////////////////////////////////////////////////////
//
//  IdeStartIo
//
//    This routine is called to start processing the next packet. 
//
//  INPUTS:
//
//    DeviceObject      - pointer to our device object
//    Irp               - pointer to the IRP
//
//  OUTPUTS:
//  
//    None.
//
//  RETURNS:
//
//    STATUS_SUCCESS
//
//      IRQL:
//
//    IRQL_DISPATCH_LEVEL
//
//  NOTES:
//
//    Since we have a single controller and disk, access to the
//    devExt is allowed, but NOT to the controllerData structure
//
//
///////////////////////////////////////////////////////////////////////////////
VOID
IdeStartIo(IN PDEVICE_OBJECT DeviceObject,
           IN PIRP Irp)
{
    PIDE_DEV_EXT devExt = (PIDE_DEV_EXT)DeviceObject->DeviceExtension;
    PIO_STACK_LOCATION ioStack;

    //
    // Get a pointer to the current I/O Stack Location
    //
    ioStack = IoGetCurrentIrpStackLocation(Irp);

    //
    // Set up the major function, length and starting sector of the transfer
    // in the device extension.  They'll be quicker to get at from the ISR
    // in the devExt than if we leave them in the IRP.
    //
    devExt->OperationType = ioStack->MajorFunction;

    devExt->RemainingTransferLength = ioStack->Parameters.Read.Length;

    devExt->FirstSectorOfRequest = 
                (ULONG)(ioStack->Parameters.Read.ByteOffset.QuadPart >>
                                devExt->ByteShiftToSector);
    //
    // Check if we're retrying this irp.
    //
    if (devExt->PacketIsBeingRetried) {

#if DBG
        DbgPrint("IdeStartIo: Retrying IRP: %x\n", Irp);
#endif
        devExt->PacketIsBeingRetried = FALSE;
        //
        // Increment the retry count. The DpcForIsr limits the number
        // of retries
        //
        devExt->IrpRetryCount++;

    } else {

        devExt->IrpRetryCount = 0;
    }

    //
    // This driver uses Direct I/O for transfer operations.
    // Map the requestor's buffer into system address space.
    //
    ASSERT(Irp->MdlAddress);
    devExt->CurrentAddress = MmGetSystemAddressForMdl(Irp->MdlAddress);

    //
    // let folks know of our intent
    //
#if DBG
    DbgPrint("IdeStartIo: Irp: 0x%0x, Func: 0x%0x VA: 0x%0x, Length: 0x%0x\n",
                Irp,
                ioStack->MajorFunction,
                devExt->CurrentAddress,
                devExt->RemainingTransferLength);
#endif
    //
    // We start the request on this device at DIRQL so seralize
    // access to the data structures and the HW registers
    //
    (VOID)KeSynchronizeExecution(devExt->ControllerData->InterruptObject,
                               IdeStartThisRequestOnDevice,
                               devExt);

    return;
}




///////////////////////////////////////////////////////////////////////////////
//
//  IdeStartThisRequestOnDevice
//
//    This routine is will start the specified request on the device
//
//  INPUTS:
//
//    Context           - actually, the devExt structure
//
//  OUTPUTS:
//  
//    None.
//
//  RETURNS:
//
//    TRUE, unless the hardware fails
//
//      IRQL:
//
//    DIRQL
//
//  NOTES:
//
//    Because this is called at DIRQL, we have access to all structures
//    in the devExt and controllerData and we can actually touch the
//    registers
//
///////////////////////////////////////////////////////////////////////////////

BOOLEAN
IdeStartThisRequestOnDevice(IN OUT PVOID Context)
{
    PIDE_DEV_EXT devExt;
    PCONTROLLER_DATA controllerData;
    NTSTATUS ntStatus;
    UCHAR controllerStatus;
    UCHAR       sectorCount, sectorNumber, cylinderLow, cylinderHigh, driveHead;

    //
    // set some locals
    //
    devExt = Context;
    controllerData = devExt->ControllerData;

    //  
    // get the current state of the controller
    //
    controllerStatus =
        READ_PORT_UCHAR(devExt->ControllerData->ControllerAddress + STATUS_REGISTER);

    //
    // We will soon cause an interrupt that will require servicing by
    // the DPC, so set the flag to note that we require a DPC.
    //
    controllerData->InterruptRequiresDpc = TRUE;

    //
    // Determine the parameters for the controller 
    //
    sectorCount = (UCHAR)(devExt->RemainingTransferLength / devExt->BytesPerSector);

    sectorNumber = (UCHAR)((devExt->FirstSectorOfRequest % 
                                                 devExt->SectorsPerTrack) + 1);

    cylinderLow = (UCHAR)(devExt->FirstSectorOfRequest /
                                    (devExt->SectorsPerTrack *
                                             devExt->TracksPerCylinder)) & 0xff;

    cylinderHigh = (UCHAR)(devExt->FirstSectorOfRequest /
                                       (devExt->SectorsPerTrack *
                                               devExt->TracksPerCylinder) >> 8);

    driveHead = (UCHAR) (((devExt->FirstSectorOfRequest /
                                        devExt->SectorsPerTrack) %
                                             devExt->TracksPerCylinder) |
                                                           devExt->DeviceUnit);

#if DBG
    DbgPrint(
        "IdeStartThisRequestOnDevice: sectorCount %x sectorNumber %x cylinderLow %x high %x driveHead %x\n",
        sectorCount, sectorNumber, cylinderLow, cylinderHigh, driveHead);
#endif

    //
    // Give the controller the cylinder and head of the start of the transfer.
    // Also tell it how many sectors we want to transfer.
    //
    WRITE_PORT_UCHAR(controllerData->ControllerAddress + SECTOR_COUNT_REGISTER,
                                                             sectorCount);

    WRITE_PORT_UCHAR(controllerData->ControllerAddress + SECTOR_NUMBER_REGISTER,
                                                             sectorNumber);

    WRITE_PORT_UCHAR(controllerData->ControllerAddress + CYLINDER_LOW_REGISTER,
                                                             cylinderLow);

    WRITE_PORT_UCHAR(controllerData->ControllerAddress + CYLINDER_HIGH_REGISTER,
                                                             cylinderHigh);

    WRITE_PORT_UCHAR(controllerData->ControllerAddress + DRIVE_HEAD_REGISTER,
                                                             driveHead);
    //
    // Actually start the request, based on the direction of the transfer.
    // Note that we've already stored that length and starting VA of
    // the transfer in the device extension (in the StartIo routine).
    //
    switch (devExt->OperationType) {

        case IRP_MJ_READ:

#if DBG
            DbgPrint("Starting a READ\n");
#endif

            //
            // Tell the controller to do a read.
            //
            // The controller will interrupt when it has a complete sector
            // of data for us to retrieve from it.
            //
            WRITE_PORT_UCHAR(controllerData->ControllerAddress + COMMAND_REGISTER,
                                                devExt->ReadCommand);

            break;

        case IRP_MJ_WRITE:

#if DBG
            DbgPrint("Starting a WRITE\n");
#endif

            //
            // Set the write precomp -- Like it matters?
            //
            WRITE_PORT_UCHAR(
                  controllerData->ControllerAddress + WRITE_PRECOMP_REGISTER,
                                              (UCHAR)(devExt->WritePrecomp));
            //
            // Give the controller the WRITE command
            //
            WRITE_PORT_UCHAR(controllerData->ControllerAddress + COMMAND_REGISTER,
                                            devExt->WriteCommand);

            //
            // The way writes work is that afer giving the controller the WRITE
            // command, we stuff a sector's worth of data into it.  BUT, before
            // we can start stuffing, the controller has to drop it's BUSY
            // status, and assert DATA_REQUEST_STATUS.  That's our signal to
            // load 'er up!
            //
            ntStatus = IdeWaitControllerReady(controllerData, 10, 5000);

            if (!NT_SUCCESS(ntStatus)) {

⌨️ 快捷键说明

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