📄 pnputils.c
字号:
for( id = 0 ; id < daisyChainDevCount ; ++id ) {
BOOLEAN bBuildStlDeviceId = FALSE;
PPDO_EXTENSION pdx = NULL;
DD((PCE)fdx,DDW,"PptFdoHandleBusRelations - changeDetected - trying to create new daisy chain PDOs\n");
if( P5SelectDaisyChainDevice( controller, id ) ) {
PCHAR devId = NULL;
// do a check to see if this is an SCM Micro device
pdx = ExAllocatePool( PagedPool | POOL_COLD_ALLOCATION, sizeof(PDO_EXTENSION) );
if( pdx != NULL ) {
RtlZeroMemory( pdx, sizeof(PDO_EXTENSION) );
pdx->Controller = fdx->PortInfo.Controller;
bBuildStlDeviceId = ParStlCheckIfStl( pdx, id );
ExFreePool( pdx );
}
if( bBuildStlDeviceId ) {
// SCM Micro device
pdx = ExAllocatePool( PagedPool | POOL_COLD_ALLOCATION, sizeof(PDO_EXTENSION) );
if( pdx != NULL ) {
ULONG DeviceIdSize;
RtlZeroMemory( pdx, sizeof(PDO_EXTENSION) );
pdx->Controller = fdx->PortInfo.Controller;
devId = ParStlQueryStlDeviceId(pdx, NULL, 0,&DeviceIdSize, TRUE);
ExFreePool (pdx);
}
} else {
// non-SCM Micro device
devId = P4ReadRawIeee1284DeviceId( controller );
}
if( devId ) {
// try to create a PDO for the daisy chain device
fdx->DaisyChainPdo[id] = P4CreatePdo( Fdo, PdoTypeDaisyChain, id, (devId+2) );
if( fdx->DaisyChainPdo[id] ) {
// have new PDO
DD((PCE)fdx,DDW,"PptFdoHandleBusRelations - new DaisyChainPdo[%d]\n",id);
++(fdx->PnpInfo.Ieee1284_3DeviceCount);
if( bBuildStlDeviceId ) {
// SCM Micro device - requires additional initialization
DD((PCE)fdx,DDW,"PptFdoHandleBusRelations - new SCM Micro DaisyChainPdo[%d]\n",id);
pdx = fdx->DaisyChainPdo[id]->DeviceExtension;
pdx->Controller = fdx->PortInfo.Controller;
ParStlCheckIfStl( pdx, 0 ); // update IEEE 1284 flags in the new pdx
}
} else {
// create PDO failed
DD((PCE)fdx,DDW,"PptFdoHandleBusRelations - create DaisyChainPdo[%d] failed\n",id);
}
ExFreePool( devId );
} else {
// devId failed
DD((PCE)fdx,DDW,"PptFdoHandleBusRelations - devId for DC %d failed\n",id);
}
P5DeselectAllDaisyChainDevices( controller );
} else {
// select failed
DD((PCE)fdx,DDW,"PptFdoHandleBusRelations - select for DC %d failed\n",id);
}
}
}
{
ULONG i;
ULONG count = 0;
i = 0;
for( i = 0 ; i < 2 ; ++i ) {
if( fdx->DaisyChainPdo[i] ) {
++count;
}
}
DD((PCE)fdx,DDW,"PptFdoHandleBusRelations - Ieee1284_3DeviceCount=%d count1 = %d\n",
fdx->PnpInfo.Ieee1284_3DeviceCount,count);
PptAssert( fdx->PnpInfo.Ieee1284_3DeviceCount == count );
}
DD((PCE)fdx,DDW,"PptFdoHandleBusRelations - daisyChainDevCount = %d, fdx->PnpInfo.Ieee1284_3DeviceCount = %d\n",
daisyChainDevCount, fdx->PnpInfo.Ieee1284_3DeviceCount);
// PptAssert( daisyChainDevCount == fdx->PnpInfo.Ieee1284_3DeviceCount );
#endif // _X86_
target_failed_to_acquire_port: // jump here if we couldn't get the port - result is that we report that nothing has changed
//
// Count the number of devices that we are going to report to PnP
// so that we can allocate a DEVICE_RELATIONS structure of the
// appropriate size.
//
if( fdx->RawPortPdo ) {
++deviceCount;
}
if( fdx->EndOfChainPdo ) {
++deviceCount;
}
if( fdx->LegacyZipPdo ) {
++deviceCount;
}
{
const ULONG maxDaisyChainId = 1;
ULONG i;
for( i=0 ; i <= maxDaisyChainId; ++i ) {
if( fdx->DaisyChainPdo[i] ) {
++deviceCount;
} else {
break;
}
}
}
if( deviceCount > 0 && fdx->RawPortPdo ) {
//
// Allocate and populate DEVICE_RELATIONS structure that we return to PnP
//
devRelSize = sizeof(DEVICE_RELATIONS) + (deviceCount-1)*sizeof(PDEVICE_OBJECT);
devRel = ExAllocatePool( PagedPool | POOL_COLD_ALLOCATION, devRelSize );
if( !devRel ) {
// release port and fail IRP
P4ReleaseBus( Fdo );
return P4CompleteRequestReleaseRemLock( Irp, STATUS_INSUFFICIENT_RESOURCES, Irp->IoStatus.Information, &fdx->RemoveLock );
}
{ // local block - begin
ULONG idx = 0;
RtlZeroMemory( devRel, devRelSize );
++(devRel->Count);
ObReferenceObject( fdx->RawPortPdo );
devRel->Objects[ idx++ ] = fdx->RawPortPdo;
if( fdx->EndOfChainPdo ) {
++(devRel->Count);
ObReferenceObject( fdx->EndOfChainPdo );
devRel->Objects[ idx++ ] = fdx->EndOfChainPdo;
}
if( fdx->LegacyZipPdo ) {
++(devRel->Count);
ObReferenceObject( fdx->LegacyZipPdo );
devRel->Objects[ idx++ ] = fdx->LegacyZipPdo;
}
{
const ULONG maxDaisyChainId = 3;
ULONG i;
for( i=0 ; i <= maxDaisyChainId; ++i ) {
if( fdx->DaisyChainPdo[i] ) {
++(devRel->Count);
ObReferenceObject( fdx->DaisyChainPdo[i] );
devRel->Objects[ idx++ ] = fdx->DaisyChainPdo[i];
} else {
break;
}
}
}
} // local block - end
PptAssert( deviceCount == devRel->Count ); // verify that our two counts match
DD((PCE)fdx,DDE,"PptFdoHandleBusRelations - reporting %d devices\n",devRel->Count);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = (ULONG_PTR)devRel;
} else {
// deviceCount <= 0 - error somewhere - likely two ports
// have the same LPTx name in the FDO stack's devnode
// RMT - this assert needs to be changed to ErrorLog msg
PptAssert(!"no RawPort device - likely multiple ports have same LPTx name - email: DFritz");
}
DD((PCE)fdx,DDW,"PptFdoHandleBusRelations - passing IRP down stack\n");
status = PptPnpPassThroughPnpIrpAndReleaseRemoveLock( fdx, Irp );
//
// Release our lock on the bus and pass Irp down the stack
//
if( acquiredPort ) {
PIO_WORKITEM workItem = IoAllocateWorkItem( Fdo );
if( workItem ) {
PIO_WORKITEM oldWorkItem = InterlockedCompareExchangePointer( &fdx->FreePortWorkItem, workItem, NULL );
if( NULL == oldWorkItem ) {
// no workitem currently in use, queue this one
IoQueueWorkItem( workItem, P5WorkItemFreePort, DelayedWorkQueue, fdx );
} else {
// there is already a workitem in use, bail out and recover as best we can
// We really shouldn't be able to get here - how in blazes did we
// acquire the port at the top of this function if the workitem
// that we queued to free the port during the previous invocation
// of this function has not yet freed the port?
PptAssertMsg( "workitem collision - port arbitration state may be hosed", (oldWorkItem != NULL) );
IoFreeWorkItem( workItem );
PptFreePort( fdx );
}
} else {
PptFreePort( fdx );
}
// DbgPrint("xxx work item to free port has been queued\n");
//DD((PCE)fdx,DDW,"PptFdoHandleBusRelations - Releasing Port\n");
//PptFreePort( fdx );
//DD((PCE)fdx,DDW,"PptFdoHandleBusRelations - Port Released\n");
} else {
DD((PCE)fdx,DDW,"PptFdoHandleBusRelations - Port Not acquired so no need to release\n");
}
DD((PCE)fdx,DDW,"PptFdoHandleBusRelations - exit\n");
return status;
}
NTSTATUS
PptPnpStartScanPciCardCmResourceList(
IN PFDO_EXTENSION Fdx,
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:
Fdx - 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;
*FoundPort = FALSE;
*FoundIrq = FALSE;
*FoundDma = FALSE;
ResourceList = irpStack->Parameters.StartDevice.AllocatedResourcesTranslated;
FullResourceDescriptor = &ResourceList->List[0];
if( FullResourceDescriptor ) {
Fdx->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
Fdx->PortInfo.OriginalController = PartialResourceDescriptor->u.Port.Start;
Fdx->PortInfo.SpanOfController = PartialResourceDescriptor->u.Port.Length;
Fdx->PortInfo.Controller = (PUCHAR)(ULONG_PTR)Fdx->PortInfo.OriginalController.QuadPart;
Fdx->AddressSpace = PartialResourceDescriptor->Flags;
*FoundPort = TRUE;
break;
case 4: // ECP base address
Fdx->PnpInfo.OriginalEcpController = PartialResourceDescriptor->u.Port.Start;
Fdx->PnpInfo.SpanOfEcpController = PartialResourceDescriptor->u.Port.Length;
Fdx->PnpInfo.EcpController = (PUCHAR)(ULONG_PTR)Fdx->PnpInfo.OriginalEcpController.QuadPart;
Fdx->EcpAddressSpace = PartialResourceDescriptor->Flags;
break;
default:
// don't know what this is - ignore it
;
}
break;
case CmResourceTypeBusNumber:
Fdx->BusNumber = PartialResourceDescriptor->u.BusNumber.Start;
break;
case CmResourceTypeInterrupt:
*FoundIrq = TRUE;
Fdx->FoundInterrupt = TRUE;
Fdx->InterruptLevel = (KIRQL)PartialResourceDescriptor->u.Interrupt.Level;
Fdx->InterruptVector = PartialResourceDescriptor->u.Interrupt.Vector;
Fdx->InterruptAffinity = PartialResourceDescriptor->u.Interrupt.Affinity;
if (PartialResourceDescriptor->Flags & CM_RESOURCE_INTERRUPT_LATCHED) {
Fdx->InterruptMode = Latched;
} else {
Fdx->InterruptMode = LevelSensitive;
}
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -