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

📄 pnp.c

📁 win2k kernel 的并口驱动程序模板
💻 C
📖 第 1 页 / 共 5 页
字号:
/*++

Copyright (C) Microsoft Corporation, 1998 - 1999

Module Name:

    parport.sys

File Name:

    pnp.c

Abstract:

    This file contains the parport AddDevice routine and
      functions for handling PnP IRPs.

    Exports:

     - PptPnpAddDevice() - PnP AddDevice routine

     - PptDispatchPnp()  - PnP Dispatch routine

     - PptPnpInitDispatchFunctionTable() - Initialize PptPnpDispatchFunctionTable[]

--*/

#include "pch.h"
#include "pnp.h"

PDEVICE_RELATIONS
PptPnpBuildRemovalRelations( 
    IN PDEVICE_EXTENSION Extension 
    )
{
    PDEVICE_RELATIONS             relations      = NULL;
    PLIST_ENTRY                   listHead       = &Extension->RemovalRelationsList;
    PLIST_ENTRY                   thisListEntry  = NULL;
    PLIST_ENTRY                   firstListEntry = NULL;
    BOOLEAN                       done           = FALSE;
    PREMOVAL_RELATIONS_LIST_ENTRY node           = NULL;
    ULONG                         count;
    ULONG                         i;
    PDEVICE_OBJECT                pDevObj;

    PptDump2(PARPNP1, ("ioctl::PptPnpBuildRemovalRelations - Enter\n"));

    // lock list
    ExAcquireFastMutex( &Extension->ExtensionFastMutex );
    
    if( IsListEmpty( listHead ) ) {
        PptDump2(PARPNP1, ("ioctl::PptPnpBuildRemovalRelationsList - Empty List\n"));
        goto targetExit;
    }

    // get count
    count = 0;
    
    while( !done ) {

        thisListEntry = RemoveHeadList( listHead );
        node = CONTAINING_RECORD( thisListEntry, REMOVAL_RELATIONS_LIST_ENTRY, ListEntry );

        if( firstListEntry == thisListEntry ) {
            // done - we've already seen this one - push back onto front of list 
            InsertHeadList( listHead, &node->ListEntry );            
            done = TRUE;
            PptDump2(PARPNP1, ("ioctl::PptPnpBuildRemovalRelationsList - Done\n"));
        } else {
            // dump node info
            PptDump2(PARPNP1, ("ioctl::PptPnpBuildRemovalRelationsList - entry= %x %wZ\n", node->DeviceObject, &node->DeviceName));
            InsertTailList( listHead, &node->ListEntry );
            ++count;
        }

        if( !firstListEntry ) {
            // save first element - use for loop termination
            PptDump2(PARPNP1, ("ioctl::PptPnpBuildRemovalRelationsList - saving first\n"));
            firstListEntry = thisListEntry;
        }
    }
    PptDump2(PARPNP1, ("ioctl::PptPnpBuildRemovalRelationsList - count= %d\n", count));

    // allocate DEVICE_RELATIONS
    relations = ExAllocatePool(PagedPool, sizeof(DEVICE_RELATIONS) + (count-1) * sizeof(PDEVICE_OBJECT));
    if( !relations ) {
        PptDump2(PARPNP1, ("ioctl::PptPnpBuildRemovalRelationsList - unable to alloc pool to hold relations\n"));        
        goto targetExit;
    }
    
    // populate DEVICE_RELATIONS
    relations->Count = count;
    for( i=0 ; i < count ; ++i ) {
        thisListEntry = RemoveHeadList( listHead );
        node = CONTAINING_RECORD( thisListEntry, REMOVAL_RELATIONS_LIST_ENTRY, ListEntry );
        PptDump2(PARPNP1, ("ioctl::PptPnpBuildRemovalRelationsList - adding device= %x %wZ\n",
                           node->DeviceObject, &node->DeviceName));
        pDevObj = node->DeviceObject;
        ObReferenceObject( pDevObj );
        relations->Objects[i] = pDevObj;
        InsertTailList( listHead, &node->ListEntry );            
    }

targetExit:

    // unlock list
    ExReleaseFastMutex( &Extension->ExtensionFastMutex );    

    return relations;
}

NTSTATUS
PptPnpStartScanPciCardCmResourceList(
    IN  PDEVICE_EXTENSION Extension,
    IN  PIRP              Irp, 
    OUT PBOOLEAN          FoundPort,
    OUT PBOOLEAN          FoundIrq,
    OUT PBOOLEAN          FoundDma
    )
/*++dvdf3

Routine Description:

    This routine is used to parse the resource list for what we
      believe are PCI parallel port cards.

    This function scans the CM_RESOURCE_LIST supplied with the Pnp 
      IRP_MN_START_DEVICE IRP, extracts the resources from the list, 
      and saves them in the device extension.

Arguments:

    Extension    - The device extension of the target of the START IRP
    Irp          - The IRP
    FoundPort    - Did we find a  Port resource?
    FoundIrq     - Did we find an IRQ  resource?
    FoundDma     - Did we find a  DMA  resource?

Return Value:

    STATUS_SUCCESS                - if we were given a resource list,
    STATUS_INSUFFICIENT_RESOURCES - otherwise

--*/
{
    NTSTATUS                        status   = STATUS_SUCCESS;
    PIO_STACK_LOCATION              irpStack = IoGetCurrentIrpStackLocation( Irp );
    PCM_RESOURCE_LIST               ResourceList;
    PCM_FULL_RESOURCE_DESCRIPTOR    FullResourceDescriptor;
    PCM_PARTIAL_RESOURCE_LIST       PartialResourceList;
    PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialResourceDescriptor;
    ULONG                           i;
    ULONG                           length;
    
    PptDump2(PARRESOURCE, ("pnp::PptPnpStartScanPciCardCmResourceList - Enter - Extension= %x , Irp= %x\n", Extension, Irp));

    *FoundPort = FALSE;
    *FoundIrq  = FALSE;
    *FoundDma  = FALSE;
    
    ResourceList = irpStack->Parameters.StartDevice.AllocatedResourcesTranslated;
    
    FullResourceDescriptor = &ResourceList->List[0];
    
    if( FullResourceDescriptor ) {
        
        Extension->InterfaceType = FullResourceDescriptor->InterfaceType;
        
        PartialResourceList = &FullResourceDescriptor->PartialResourceList;
        
        for (i = 0; i < PartialResourceList->Count; i++) {
            
            PartialResourceDescriptor = &PartialResourceList->PartialDescriptors[i];
            
            switch (PartialResourceDescriptor->Type) {
                
            case CmResourceTypePort:
                
                length = PartialResourceDescriptor->u.Port.Length;

                //
                // Use a heuristic based on length to guess which register set is
                //   SPP+EPP, which is ECP, and which is PCI Config or other.
                //
                switch( length ) {

                case 8: // SPP + EPP base address

                    PptDump2(PARRESOURCE, ("pnp::PptPnpStartScanPciCardCmResourceList - found SPP+EPP\n"));
                    Extension->PortInfo.OriginalController = PartialResourceDescriptor->u.Port.Start;
                    Extension->PortInfo.SpanOfController   = PartialResourceDescriptor->u.Port.Length;
                    Extension->PortInfo.Controller         = (PUCHAR)(ULONG_PTR)Extension->PortInfo.OriginalController.QuadPart;
                    Extension->AddressSpace                = PartialResourceDescriptor->Flags;
                    *FoundPort = TRUE;
                    break;

                case 4: // ECP base address
                    
                    PptDump2(PARRESOURCE, ("pnp::PptPnpStartScanPciCardCmResourceList - found ECP\n"));
                    Extension->PnpInfo.OriginalEcpController = PartialResourceDescriptor->u.Port.Start;
                    Extension->PnpInfo.SpanOfEcpController   = PartialResourceDescriptor->u.Port.Length;
                    Extension->PnpInfo.EcpController         = (PUCHAR)(ULONG_PTR)Extension->PnpInfo.OriginalEcpController.QuadPart;
                    Extension->EcpAddressSpace               = PartialResourceDescriptor->Flags;
                    break;

                default:
                    // don't know what this is - ignore it
                    PptDump2(PARRESOURCE, ("pnp::PptPnpStartScanPciCardCmResourceList - unrecognised Port length\n"));
                }
                break;
                
            case CmResourceTypeBusNumber:
                
                Extension->BusNumber = PartialResourceDescriptor->u.BusNumber.Start;
                break;
                
            case CmResourceTypeInterrupt:
                
                *FoundIrq = TRUE;
                Extension->FoundInterrupt       = TRUE;
                Extension->InterruptLevel       = (KIRQL)PartialResourceDescriptor->u.Interrupt.Level;
                Extension->InterruptVector      = PartialResourceDescriptor->u.Interrupt.Vector;
                Extension->InterruptAffinity    = PartialResourceDescriptor->u.Interrupt.Affinity;
                
                if (PartialResourceDescriptor->Flags & CM_RESOURCE_INTERRUPT_LATCHED) {
                    
                    Extension->InterruptMode = Latched;
                    
                } else {
                    
                    Extension->InterruptMode = LevelSensitive;
                }
                break;
                
            case CmResourceTypeDma:
                
                *FoundDma = TRUE;
                Extension->DmaChannel   = PartialResourceDescriptor->u.Dma.Channel;
                Extension->DmaPort      = PartialResourceDescriptor->u.Dma.Port;
                Extension->DmaWidth     = PartialResourceDescriptor->Flags;
                break;
                
            default:

                break;

            } // end switch( PartialResourceDescriptor->Type )
        } // end for(... ; i < PartialResourceList->Count ; ...)
    } // end if( FullResourceDescriptor )
    
    return status;
}

BOOLEAN PptIsPci(
    PDEVICE_EXTENSION Extension, 
    PIRP              Irp 
)
/*++

Does this look like a PCI card? Return TRUE if yes, FALSE otherwise

--*/
{
    NTSTATUS                        status   = STATUS_SUCCESS;
    PIO_STACK_LOCATION              irpStack = IoGetCurrentIrpStackLocation( Irp );
    PCM_RESOURCE_LIST               ResourceList;
    PCM_FULL_RESOURCE_DESCRIPTOR    FullResourceDescriptor;
    PCM_PARTIAL_RESOURCE_LIST       PartialResourceList;
    PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialResourceDescriptor;
    ULONG                           i;
    ULONG                           portResourceDescriptorCount = 0;
    BOOLEAN                         largePortRangeFound         = FALSE;
    ULONG                           rangeLength;
    
#if DBG
    PptDump2(PARRESOURCE, ("pnp::PptIsPci - Enter - Extension= %x , Irp= %x\n", Extension, Irp));
#else
    UNREFERENCED_PARAMETER( Extension );
#endif

    //
    // If there are more than 2 IO resource descriptors, or if any IO resource
    //   descriptor has a range > 8 bytes, then assume that this is a PCI device
    //   and requires non-traditional handling.
    //

    ResourceList = irpStack->Parameters.StartDevice.AllocatedResourcesTranslated;
    
    if (ResourceList == NULL) {
        // we weren't given any resources
        PptDump2(PARRESOURCE, ("pnp::PptIsPCI - No Resources - AllocatedResourcesTranslated == NULL\n") );
        return FALSE;
    }

    FullResourceDescriptor = &ResourceList->List[0];
    
    if (FullResourceDescriptor) {
        
        PptDump2(PARRESOURCE, ("pnp::PptIsPCI - Interface = %d\n", FullResourceDescriptor->InterfaceType));
        
        PartialResourceList = &FullResourceDescriptor->PartialResourceList;
        
        for (i = 0; i < PartialResourceList->Count; i++) {
            
            PartialResourceDescriptor = &PartialResourceList->PartialDescriptors[i];
            
            switch (PartialResourceDescriptor->Type) {
                
            case CmResourceTypePort:
                
                rangeLength = PartialResourceDescriptor->u.Port.Length;
                PptDump2(PARRESOURCE, ("pnp::PptIsPCI - CmResourceTypePort - Start= %I64x, Length= %x , \n",
                                       PartialResourceDescriptor->u.Port.Start.QuadPart,
                                       rangeLength));

                ++portResourceDescriptorCount;

                if( rangeLength > 8 ) {
                    PptDump2(PARRESOURCE, ("pnp::PptIsPCI - found largePortRange = %x\n", rangeLength));
                    largePortRangeFound = TRUE;
                }

                break;
                
            default:
                PptDump2(PARRESOURCE, ("pnp::PptIsPCI - Other ResourceType\n"));
            } // end switch( PartialResourceDescriptor->Type )
        } // end for(... ; i < PartialResourceList->Count ; ...)
    } // end if( FullResourceDescriptor )
    
    if( (portResourceDescriptorCount > 2) || (TRUE == largePortRangeFound) ) {
        PptDump2(PARRESOURCE, ("pnp::PptIsPCI - looks like PCI\n"));
        return TRUE;
    } else {
        PptDump2(PARRESOURCE, ("pnp::PptIsPCI - does not look like PCI\n"));
        return FALSE;
    }
}

VOID
PptCompleteRequest(
    IN PIRP Irp,
    IN CCHAR PriorityBoost
    )
{
#if 0
    PptDump2(PARENTRY, ("pnp::PptCompleteRequest - completing IRP= %x , UserEvent= %x\n",Irp, Irp->UserEvent));
    if( Irp->UserEvent ) {
        ASSERT_EVENT( Irp->UserEvent );
    }
#endif
    IoCompleteRequest(Irp, PriorityBoost);
}


//
// Table of pointers to functions for handling PnP IRPs. 
//
// IrpStack->MinorFunction is used as an index into the table. 
//   (Special handling required if IrpStack->MinorFunction > table size.)
//
//  - Initialized by PptPnpInitDispatchFunctionTable()
//
//  - Used by PptDispatchPnp()
// 
// 
static PDRIVER_DISPATCH PptPnpDispatchFunctionTable[ MAX_PNP_IRP_MN_HANDLED + 1 ];

VOID
PptPnpInitDispatchFunctionTable(
    VOID
    )
/*++dvdf8

Routine Description:

    This function is called from DriverEntry() to initialize
      PptPnpDispatchFunctionTable[] for use as a call table
      by the PnP dispatch routine PptDispatchPnp().

Arguments:

    none

⌨️ 快捷键说明

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