📄 pnp.c
字号:
/*++
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 + -