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

📄 ide.c

📁 硬盘驱动的例子
💻 C
📖 第 1 页 / 共 4 页
字号:
///////////////////////////////////////////////////////////////////////////////
//
//  (C) Copyright 1995 - 1998 OSR Open Systems Resources, Inc.
//	All Rights Reserved
//      Based on a previous work by Microsoft Corporation
//      Copyright (c) 1991, 1992, 1993  Microsoft Corporation
//
//    This sofware is supplied for instructional purposes only.
//
//      OSR Open Systems Resources, Inc. (OSR) expressly disclaims any warranty
//      for this software.  THIS SOFTWARE IS PROVIDED  "AS IS" WITHOUT WARRANTY
//      OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION,
//      THE IMPLIED WARRANTIES OF MECHANTABILITY OR FITNESS FOR A PARTICULAR
//      PURPOSE.  THE ENTIRE RISK ARISING FROM THE USE OF THIS SOFTWARE REMAINS
//      WITH YOU.  OSR's entire liability and your exclusive remedy shall not
//      exceed the price paid for this material.  In no event shall OSR or its
//      suppliers be liable for any damages whatsoever (including, without
//      limitation, damages for loss of business profit, business interruption,
//      loss of business information, or any other pecuniary loss) arising out
//      of the use or inability to use this software, even if OSR has been
//      advised of the possibility of such damages.  Because some states/
//      jurisdictions do not allow the exclusion or limitation of liability for
//      consequential or incidental damages, the above limitation may not apply
//      to you.
//
//    This driver is the example Programmed I/O device driver that
//    accompanies the book Windows NT Device Driver Development, by
//    Peter Viscarola and W. Anthony Mason, (c) 1998 OSR Open Systems
//    Resources, Inc. and published by MacMillan Technical Publishing
//    ISBN 1578700582.  
//
//
//  OSR Open Systems Resources, Inc.
//  105 Route 101A Suite 19
//  Amherst, NH 03031  (603) 595-6500 FAX: (603) 595-6503
//  email bugs to: bugs@osr.com
//
//
//  MODULE:
//
//      $Workfile: ide.c $
//
//  ABSTRACT:
//
//      This file contains the initial entry point for the OSR Sample
//      Programmed I/O device driver for the IDE (AT) Disk Controller.
//
//  AUTHOR:
//
//      Open Systems Resources, Inc.
// 
//  REVISION:   
//
//
///////////////////////////////////////////////////////////////////////////////

#include "ntddk.h"                      // main NT include
#include "ntdddisk.h"                   // disk driver IOCTL definitions
#include "ntddscsi.h"                   // scsi IOCTL defintions
#include "hw.h"                         // the access macro/definitions
#include "ide.h"                        // general declarations/structures
#include "utils.h"                      // IdeWaitController utilities

//
// static forward declarations
//


static VOID
FinishIrp(IN PIDE_DEV_EXT devExt,
          IN NTSTATUS NtStatus);

static BOOLEAN
ResetDisk(IN PVOID Context);


///////////////////////////////////////////////////////////////////////////////
//
//  IdeDispatchCreateClose
//
//    This routine handles the Create and Close IRPs.  Since we're a 
//    disk driver, this only completes the IRP
//
//  INPUTS:
//
//    DeviceObject      - pointer to our device object
//    Irp               - pointer to the IRP
//
//  OUTPUTS:
//  
//    None.
//
//  RETURNS:
//
//    STATUS_SUCCESS, any time, all the time
//
//      IRQL:
//
//    IRQL_PASSIVE_LEVEL
//
//  NOTES:
//
///////////////////////////////////////////////////////////////////////////////
NTSTATUS
IdeDispatchCreateClose(IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp)
{

    //
    // Nothing to do... Just complete the request with success and return
    //

    Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = 0;

    //
    // Complete the irp with no increase in priority 
    //

    IoCompleteRequest(Irp, IO_NO_INCREMENT);

    //
    // return the success
    //

    return STATUS_SUCCESS;
}



///////////////////////////////////////////////////////////////////////////////
//
//  IdeDispatchDeviceControl
//
//    This routine handles the device control IRPs
//
//  INPUTS:
//
//    DeviceObject      - pointer to our device object
//    Irp               - pointer to the IRP
//
//  OUTPUTS:
//  
//    None.
//
//  RETURNS:
//
//    STATUS_SUCCESS upon completion of the request, otherwise
//    STATUS_INVALID_DEVICE_REQUEST , STATUS_INVALID_PARAMETER
//
//      IRQL:
//
//    IRQL_PASSIVE_LEVEL
//
//  NOTES:
//
///////////////////////////////////////////////////////////////////////////////
NTSTATUS
IdeDispatchDeviceControl(IN PDEVICE_OBJECT DeviceObject,
                        IN OUT PIRP Irp)
{
    PPARTITION_DATA partitionData;
    PIDE_DEV_EXT devExt;
    PCONTROLLER_DATA controllerData;
    PIO_STACK_LOCATION ioStack;
    NTSTATUS ntStatus;

    //
    // Set up some locals
    //
    partitionData = DeviceObject->DeviceExtension;
    devExt = partitionData->Partition0;
    controllerData = devExt->ControllerData;




        //
    // Get the current stack location
    //
    ioStack = IoGetCurrentIrpStackLocation(Irp);

    //
    // Determine which I/O control code was specified.  
    // In this sample driver, we support the absolute minimum IOCTL
    // necessar.  See NTDDDISK.H for the complete set of definitions.
    //
    switch (ioStack->Parameters.DeviceIoControl.IoControlCode) {

        //
        // Return the drive geometry
        //
        case IOCTL_DISK_GET_DRIVE_GEOMETRY: 

            //
            // Validate the size of the requestor's buffer
            //
            if (ioStack->Parameters.DeviceIoControl.OutputBufferLength <
                    sizeof(DISK_GEOMETRY)) {

            Irp->IoStatus.Information = 0;
            Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;

            } else {

                PDISK_GEOMETRY obuf;

                //
                // Since the IOCTL is specified as METHOD_BUFFERED, the
                // output buffer is in system pool, pointed to by the
                // AssociatedIrp.SystemBuffer field in the IRP
                //
                obuf = (PDISK_GEOMETRY)Irp->AssociatedIrp.SystemBuffer;

                //
                // This is known to be a fixed hard disk, so we return
                // FixedMedia (defined in NTDDDISK.H)
                //
                obuf->MediaType = FixedMedia;

                //
                // The actual disk geometry is retrieved from the 
                // devExt structure.  This was filled in during 
                // device initialization (see InitializeDisk())
                //
                obuf->Cylinders.QuadPart = devExt->PretendNumberOfCylinders;
                obuf->TracksPerCylinder = devExt->PretendTracksPerCylinder;
                obuf->SectorsPerTrack = devExt->PretendSectorsPerTrack;
                obuf->BytesPerSector = devExt->BytesPerSector; 

                //
                // Fill in the I/O Status Block for completion
                //
                Irp->IoStatus.Information = sizeof(DISK_GEOMETRY);

                Irp->IoStatus.Status = STATUS_SUCCESS;

            }

            break ;

        //
        // Return the information about the partition specified by the
        // device object.
        //
        case IOCTL_DISK_GET_PARTITION_INFO: 

            //
            // Validate the size of the requestor's buffer
            //
            if (ioStack->Parameters.DeviceIoControl.OutputBufferLength <
                    sizeof(PARTITION_INFORMATION)) {

                Irp->IoStatus.Information = 0;
                Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;

            } else {


                //
                // Is this request for the physical device (i.e. Partition0)?
                //
                if (partitionData == (PPARTITION_DATA)devExt) {

                    //
                    // The request is for the physical device.  This isn't
                    // a sensible request... so fail it.
                    //
                    Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;

                } else {

                    PPARTITION_INFORMATION obuf;

                    //
                    // The request is for an actual partition on the drive,
                    // not the physical device.

                    //
                    // Since this IOCTL uses METHOD_BUFFERED, we locate
                    // the intermediate buffer to be used to return data to
                    // the requestor in AssociatedIrp.SystemBuffer
                    //
                    obuf = (PPARTITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;

                    //
                    // Fill in the partition information obtained during
                    // the initilaization process (see InitalizeDisk()
                    //
                    obuf->PartitionType = partitionData->Pi.PartitionType;
                    obuf->BootIndicator = partitionData->Pi.BootIndicator;

                    //
                    // If it wasn't regcognized, we wouldn't have a partition
                    // device object...
                    //
                    obuf->RecognizedPartition = TRUE;

                    obuf->RewritePartition = FALSE;
                    obuf->PartitionNumber = partitionData->Pi.PartitionNumber;
                    obuf->StartingOffset = partitionData->Pi.StartingOffset;
                    obuf->PartitionLength = partitionData->Pi.PartitionLength;
                    obuf->HiddenSectors = partitionData->Pi.HiddenSectors;

                    //
                    // Set the length of the returned data in the Information
                    // field and set the STATUS_SUCCESS for the Irp
                    //
                    Irp->IoStatus.Information = sizeof(PARTITION_INFORMATION);

                    Irp->IoStatus.Status = STATUS_SUCCESS;
                }

            }

            break ;

        //
        // Set some partition information
        //
        case IOCTL_DISK_SET_PARTITION_INFO:

            //
            // Validate the input buffer size.  If it's not correct,
            // complete the IRP with an error status.
            //
            if (ioStack->Parameters.DeviceIoControl.InputBufferLength <
                    sizeof(SET_PARTITION_INFORMATION)) {

                Irp->IoStatus.Information = 0;
                Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;

            } else {


                //
                // Is the requestor trying to set partition info for
                // Partion zero, which is the physical disk?
                //
                if (partitionData == (PPARTITION_DATA)devExt) {

                    //
                    // Can't set the part info on a physical disk, silly!
                    //
                    Irp->IoStatus.Information = 0;
                    Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;

                } else {

                    PSET_PARTITION_INFORMATION inputBuffer;

                    //
                    // Since the IOCTL uses METHOD_BUFFERED, we locate
                    // the intermediate buffer with the requestor's set
                    // partition information in it.
                    //
                    inputBuffer =
                            (PSET_PARTITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;

                    //
                    // Invoke the kernel function to set the partition information
                    //

                    //
                    // If this were a REAL IDE driver, we might want to VALIDATE
                    // the partition information being set before lofting this
                    // request down to the I/O Manager.  But seeing as how
                    // this is just a sample...
                    //
                    ntStatus = IoSetPartitionInformation(devExt->DeviceObject,
                            devExt->BytesPerSector,
                            partitionData->PartitionOrdinal,
                            inputBuffer->PartitionType);

                    //
                    // Update our information
                    //
                    if (NT_SUCCESS(ntStatus)) {

                        partitionData->Pi.PartitionType = inputBuffer->PartitionType;
                    }

                    //
                    // 
                    //
                    Irp->IoStatus.Status = ntStatus;
                    Irp->IoStatus.Information = 0;
                }

            }
            break ;

        //
        // Return the partition layout for the physical drive.  Note that
        // the layout is returned for the actual physical drive, regardless
        // of which partition was specified for the request.
        //
        case IOCTL_DISK_GET_DRIVE_LAYOUT: 

            //
            // Check that the input buffer is of the correct size.
            // If not, then return an error
            //
            if (ioStack->Parameters.DeviceIoControl.OutputBufferLength <
                    sizeof(DRIVE_LAYOUT_INFORMATION)) {

                Irp->IoStatus.Information = 0;
                Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;

            } else {

                PDRIVE_LAYOUT_INFORMATION partitionList;

                //
                // Call the service to read the partition table.  The
                // result will be stored in a "partition buffer" allocated
                // by the IoReadPartitionTable() function in non-paged
                // pool.  We free this memory below...
                //
                ntStatus = IoReadPartitionTable(devExt->DeviceObject,
                        devExt->BytesPerSector,
                        FALSE,
                        &partitionList);

                //
                // if the read fails, then set the status
                //
                if (!NT_SUCCESS(ntStatus)) {

                    Irp->IoStatus.Information = 0;

                    Irp->IoStatus.Status = ntStatus;

                } else {

                    ULONG tempSize;

                    //
                    // The disk layout has been returned in the partitionList
                    // buffer.
                    //
                    // First, we must determine the size of the returned
                    // information to see if the data will fit into the
                    // IOCTL buffer.   The DRIVE_LAYOUT_INFORMATION
                    // structure (defined in NTDDDISK.H) consists of a
                    // variable number of PARTITION_INFORMATION structures
                    // (also defined in NTDDDISK.H).  So, first we use the
                    // MACRO FIELD_OFFSET (defined in NTDEF.H) which
                    // will determine the size of the DRIVE_LAYOUT_INFORMATION
                    // structure less the start of the PARTITION_INFORMATION
                    // structures.
                    //
                    tempSize = FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION,
                            PartitionEntry[0]);

                    //
                    // We now add to tempSize the size of all of the 
                    // PARTITION_INFORMATION structures
                    //
                    tempSize += partitionList->PartitionCount *
                            sizeof(PARTITION_INFORMATION);

                    //
                    // If this total size is larger than the requestor's
                    // OutputBufferLength, then return an error
                    //
                    if (tempSize >
                            ioStack->Parameters.DeviceIoControl.OutputBufferLength) {

                        Irp->IoStatus.Information = 0;

                        Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;

                    } else {

                        //
                        // The buffer is large enough, so move the data
                        //
                        RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer,
                                partitionList,
                                tempSize);

⌨️ 快捷键说明

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