📄 pnp.cpp
字号:
*
* Function : HandleStartDevice
*
* Description: Handle the IRP_MN_START_DEVICE PnP request
*
******************************************************************************/
NTSTATUS PnpStartDevice(IN PDEVICE_OBJECT fdo,
IN PIRP pIrp )
{ //HandleStartDevice
NTSTATUS status;
PIO_STACK_LOCATION stack;
//First let all lower-level drivers handle this request. In this
//particular sample, the only lower-level driver should be the physical
//device created by the bus driver, but there could theoretically be any
//number of intervening bus filter devices. Those drivers may need to do
//some setup at this point in time before they'll be ready to handle
//non-PnP IRP's.
pIrp->IoStatus.Status = STATUS_SUCCESS;
status = ForwardAndWait(fdo,pIrp); //Send IRP to lower driver and wait for finishing
if (!NT_SUCCESS(status))
{
return CompleteRequest(pIrp, status);
}
stack = IoGetCurrentIrpStackLocation(pIrp);
// Assign resources to the devices
status = StartDevice(fdo,
&stack->Parameters.StartDevice.AllocatedResources->List[0].PartialResourceList,
&stack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0].PartialResourceList);
return CompleteRequestInfo(pIrp,status,0);
} //HandleStartDevice
/******************************************************************************
*
* Function : StartDevice
*
* Description: Start a device
*
******************************************************************************/
NTSTATUS StartDevice(IN PDEVICE_OBJECT fdo,
IN PCM_PARTIAL_RESOURCE_LIST ResourceListRaw,
IN PCM_PARTIAL_RESOURCE_LIST ResourceList)
{ //StartDevice
ULONG i;
ULONG vector;
KIRQL IrqL;
BOOLEAN GotInterrupt;
BOOLEAN GotPdcMem;
BOOLEAN GotBaseMem;
NTSTATUS status;
KAFFINITY affinity;
BOOLEAN irqshare;
KINTERRUPT_MODE mode;
PDEVICE_EXTENSION pdx;
PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceRaw;
PCM_PARTIAL_RESOURCE_DESCRIPTOR Resource;
pdx = (PDEVICE_EXTENSION)fdo->DeviceExtension;
if (pdx->GotResource)
return STATUS_SUCCESS;
GotInterrupt= FALSE;
GotPdcMem = FALSE;
GotBaseMem = FALSE;
ResourceRaw = ResourceListRaw->PartialDescriptors;
Resource = ResourceList->PartialDescriptors;
KdPrint((DBG_NAME "Start Device Start.\n"));
for (i = 0; i < ResourceListRaw->Count; ++i, ++Resource, ++ResourceRaw)
{
switch (ResourceRaw->Type)
{
case CmResourceTypeInterrupt://中断资源
GotInterrupt = TRUE;
IrqL = (KIRQL) Resource->u.Interrupt.Level;
vector = Resource->u.Interrupt.Vector;
affinity = Resource->u.Interrupt.Affinity;
if (ResourceRaw->Flags == CM_RESOURCE_INTERRUPT_LATCHED)
{
mode = Latched;
}
else
{
mode = LevelSensitive;
}
irqshare = Resource->ShareDisposition == CmResourceShareShared;
KdPrint((DBG_NAME "ResouceType: Interrupt:Vector:0x%x(Translated=0x%x)\n",
ResourceRaw->u.Interrupt.Vector, vector));
KdPrint((DBG_NAME " IRQL:0x%x(Translated=0x%x)Affinity:0x%x(Translated=0x%x)\n",
ResourceRaw->u.Interrupt.Level, IrqL,
ResourceRaw->u.Interrupt.Affinity, affinity));
break;
case CmResourceTypePort:
//PCI9052内部的寄存器占用一个IO资源和Mem资源,可以不用IO资源
KdPrint((DBG_NAME "Port is reqired."));
KdPrint((DBG_NAME "ResoureType: I/O Port:Address:0x%x(Translated=0x%x);Size:0x%x.\n",
ResourceRaw->u.Port.Start.LowPart,
Resource->u.Port.Start.LowPart,
ResourceRaw->u.Port.Length));
break;
case CmResourceTypeMemory:
KdPrint((DBG_NAME "ResoureType: Memory Space:Address:0x%x(Translated=0x%x);Size: 0x%x.\n",
ResourceRaw->u.Memory.Start.LowPart,
Resource->u.Memory.Start.LowPart,
ResourceRaw->u.Memory.Length));
//其实在对Mem资源进行读取时,按照PCI BAR0-5进行的,可以根据数量来判断各个BAR.
if (ResourceRaw->u.Memory.Length == 0x100)
{ //PCI Bar 0
pdx->LocalRegisterPhysicalMemBase = ResourceRaw->u.Memory.Start;
pdx->LocalRegisterMemCount = ResourceRaw->u.Memory.Length;
pdx->LocalRegisterMemBase = (ULONG *)MmMapIoSpace(pdx->LocalRegisterPhysicalMemBase,
pdx->LocalRegisterMemCount,MmNonCached);
KdPrint((DBG_NAME "The MEM Base 0 is %x; Count is %x.\n",pdx->LocalRegisterMemBase, pdx->LocalRegisterMemCount));
if (pdx->LocalRegisterMemBase == NULL)
{
// PCI BAR 0 is required for register access
KdPrint((DBG_NAME "PDC4000: ERROR - BAR 0 mapping is required\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
GotBaseMem = TRUE;
} //PCI Bar 0
else
{ //PCI Bar 2
pdx->PdcPhysicalMemBase0 = ResourceRaw->u.Memory.Start;
pdx->PdcMemCount0 = ResourceRaw->u.Memory.Length;
pdx->PdcMemBase0 = (ULONG *)MmMapIoSpace(pdx->PdcPhysicalMemBase0,
pdx->PdcMemCount0, MmNonCached);
KdPrint((DBG_NAME "The MEM Base SJA1000 is %x;Count is %x.\n", pdx->PdcMemBase0, pdx->PdcMemCount0));
if (pdx->PdcMemBase0 == NULL)
{
KdPrint((DBG_NAME "ERROR - Unable to map SJA1000.\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
GotPdcMem = TRUE;
} //PCI Bar 2
break;
//其他资源一般没有,可默认处理
case CmResourceTypeNull:
KdPrint((DBG_NAME "Type: Null (unsupported)\n"));
break;
case CmResourceTypeDma:
KdPrint((DBG_NAME "Type: DMA (unsupported)\n"));
break;
case CmResourceTypeDeviceSpecific:
KdPrint((DBG_NAME "Type: Device Specific (unsupported)"));
break;
case CmResourceTypeBusNumber:
KdPrint((DBG_NAME "Type: Bus Number (unsupported)\n"));
break;
// NonArbitrated & ConfigData are currently #defined as the same number
case CmResourceTypeConfigData:
KdPrint((DBG_NAME "Type: Non-Arbitrated or Config Data (unsupported)\n"));
break;
case CmResourceTypeDevicePrivate:
KdPrint((DBG_NAME "Type: Device Private Data (unsupported)\n"));
break;
case CmResourceTypePcCardConfig:
KdPrint((DBG_NAME "Type: PC Card Configuration (unsupported)\n"));
break;
case CmResourceTypeMfCardConfig:
KdPrint((DBG_NAME "Type: Multi-function Card Configuration (unsupported)\n"));
break;
default:
KdPrint((DBG_NAME "Type: ?Unknown Resource Type?\n"));
break;
}
}
// Make sure BAR 0 exists or the device can't be started
if (!GotBaseMem)
{
KdPrint((DBG_NAME "PDC4000: ERROR - BAR 0 address not configured, unable to load driver."));
return STATUS_INSUFFICIENT_RESOURCES;
}
if (!GotPdcMem)
{
if(pdx->LocalRegisterMemBase)
{
MmUnmapIoSpace(pdx->LocalRegisterMemBase, pdx->LocalRegisterMemCount); //Free Base Memory.
KdPrint((DBG_NAME "PDC4000: ERROR - CanMemBase.\n"));
}
return STATUS_INSUFFICIENT_RESOURCES;
}
//连接中断
if (GotInterrupt)
{
KdPrint((DBG_NAME "Get Interrupt.\n"));
// 首先Disable the PCI interrupt
DisablePciInterrupt(pdx);
//连接中断
status = IoConnectInterrupt(&pdx->pInterruptObject,(PKSERVICE_ROUTINE)OnInterrupt,
(PVOID)pdx,NULL,vector,IrqL,IrqL,mode,irqshare,affinity,FALSE); //(PVOID)
KdPrint((DBG_NAME "OK, I haved Connect Interruput!\n"));
if (!NT_SUCCESS(status))
{
pdx->pInterruptObject = NULL;
return status;
}
else
{ // Re-enable the PCI Interrupt
KdPrint((DBG_NAME "OK, Let's enable interrupt.\n"));
if (pdx->pInterruptObject == NULL)
{
KdPrint((DBG_NAME "Interrupt object is NULL.\n"));
}
//同步Enable interrupt.
KeSynchronizeExecution(pdx->pInterruptObject,(PKSYNCHRONIZE_ROUTINE)EnablePciInterrupt,pdx);
KdPrint((DBG_NAME "Have Enabled Interrupt.\n"));
}
}
else
{
KdPrint((DBG_NAME "No interrupt found.\n"));
//Free haved mapped memories.
MmUnmapIoSpace(pdx->LocalRegisterMemBase, pdx->LocalRegisterMemCount);
MmUnmapIoSpace(pdx->PdcMemBase0, pdx->PdcMemCount0);
pdx->pInterruptObject = NULL;
}
//Set DMA
DEVICE_DESCRIPTION dd;
RtlZeroMemory(&dd, sizeof(dd));
dd.Version = DEVICE_DESCRIPTION_VERSION;
dd.Master = TRUE;
dd.InterfaceType = InterfaceTypeUndefined;
dd.MaximumLength = MAX_DMA_LENGTH;
dd.Dma32BitAddresses = TRUE;
dd.Dma64BitAddresses = FALSE;
dd.ScatterGather = TRUE;
pdx->DmaInfo[0].pDmaAdapterObject = IoGetDmaAdapter(pdx->pPhysicalDeviceObject,
&dd,
&pdx->DmaInfo[0].lNumberOfMapRegisters);
if (pdx->DmaInfo[0].pDmaAdapterObject == NULL)
{
KdPrint((DBG_NAME "Fatal Error: DmaAdapterObject is NULL!!!!!!\n"));
}
pdx->DmaInfo[0].lCommonBufferSize = COMMON_BUFFER_SIZE; //the length of the common buffer.
pdx->DmaInfo[0].vaCommonBuffer =
(*pdx->DmaInfo[0].pDmaAdapterObject->DmaOperations->AllocateCommonBuffer)
(pdx->DmaInfo[0].pDmaAdapterObject, //AdapterObject
pdx->DmaInfo[0].lCommonBufferSize, //Size
&pdx->DmaInfo[0].paCommonBuffer, //LogicalAddress
FALSE); //CacheEnabled
if (pdx->DmaInfo[0].vaCommonBuffer == NULL)
{
KdPrint((DBG_NAME "Don't Allocate the Common Buffer.\n"));
}
KdPrint((DBG_NAME "Have Allocate the Common Buffer.\n"));
//Use the common buffer as the SGL Descriptor buffer.
pdx->DmaInfo[0].pSGE = (PPCI9054_SCATTER_GATHER_ELEMENT)(pdx->DmaInfo[0].vaCommonBuffer);
pdx->DmaInfo[0].lMapRegisterCount = SGE_MAX_COUNT;
pdx->GotResource = TRUE;
KdPrint((DBG_NAME "Start Device end.\n"));
return STATUS_SUCCESS;
} //StartDevice
/******************************************************************************
*
* Function : HandleStopDevice
*
* Description: Handle the IRP_MN_STOP_DEVICE PnP request
*
******************************************************************************/
NTSTATUS PnpStopDevice(IN PDEVICE_OBJECT fdo,
IN PIRP pIrp)
{
StopDevice(fdo);
return DefaultPnpHandler(fdo,pIrp);
} //HandleStopDevice
/******************************************************************************
*
* Function : StopDevice
*
* Description: Stop a device
*
******************************************************************************/
VOID StopDevice(IN PDEVICE_OBJECT fdo)
{ //StopDevice
DEVICE_EXTENSION *pdx;
pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
if (!pdx->GotResource)
return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -