21,597
社区成员
发帖
与我相关
我的任务
分享
NTSTATUS StartDevice(IN PDEVICE_OBJECT fdo,
IN PCM_PARTIAL_RESOURCE_LIST ResourceListRaw,
IN PCM_PARTIAL_RESOURCE_LIST ResourceList)
{
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;
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;
DbgPrint("ResouceType: Interrupt:Vector:0x%x(Translated=0x%x)",
ResourceRaw->u.Interrupt.Vector, vector);
DbgPrint("IRQL:0x%x(Translated=0x%x)Affinity:0x%x(Translated=0x%x).",
ResourceRaw->u.Interrupt.Level, IrqL,
ResourceRaw->u.Interrupt.Affinity, affinity);
break;
//PCI9052内部的寄存器占用一个IO资源
case CmResourceTypePort:
DbgPrint("ResoureType: I/O Port:Address:0x%x(Translated=0x%x);Size:0x%x.",
ResourceRaw->u.Port.Start.LowPart,
Resource->u.Port.Start.LowPart,
ResourceRaw->u.Port.Length);
break;
//PCI9052内部的寄存器占用一个Mem资源,进行读取时按BAR0-5进行,根据数量判断各个BAR
case CmResourceTypeMemory:
DbgPrint("ResoureType: Memory Space:Address:0x%x(Translated=0x%x);Size: 0x%x.",
ResourceRaw->u.Memory.Start.LowPart,
Resource->u.Memory.Start.LowPart,
ResourceRaw->u.Memory.Length);
if(ResourceRaw->u.Memory.Length == 0x80) //PCI Bar 0
{
pdx->PhysicalMemBase = ResourceRaw->u.Memory.Start;
pdx->MemCount = ResourceRaw->u.Memory.Length;
pdx->MemBase = (ULONG *)MmMapIoSpace(pdx->PhysicalMemBase, //MmMapIoSpace:将物理地址转换成虚拟地址的一个函数。
pdx->MemCount,
MmNonCached);
DbgPrint("The MEM Base 0 is %x; Count is %x.",pdx->MemBase,pdx->MemCount);
if(pdx->MemBase == NULL)
{
DbgPrint("PCI_DEV: ERROR - BAR 0 mapping is required\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
GotBaseMem = TRUE;
}
else //PCI Bar 2
{
pdx->PdcPhysicalMemBase = ResourceRaw->u.Memory.Start;
pdx->PdcMemCount = ResourceRaw->u.Memory.Length;
pdx->PdcMemBase = (ULONG *)MmMapIoSpace(pdx->PdcPhysicalMemBase,
pdx->PdcMemCount,
MmNonCached);
DbgPrint("The MEM Base 2 is %x;Count is %x.",pdx->PdcMemBase,pdx->PdcMemCount);
if (pdx->PdcMemBase == NULL)
{
DbgPrint("ERROR - Unable to map SJA1000.\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
GotPdcMem = TRUE;
}
break;
default:
break;
}
}
if(!GotBaseMem)
{
DbgPrint("PCI_DEV: ERROR - BAR 0 address not configured, unable to load driver.");
return STATUS_INSUFFICIENT_RESOURCES;
}
if(!GotPdcMem)
{
if(pdx->MemBase)
{
MmUnmapIoSpace(pdx->MemBase,pdx->MemCount);
DbgPrint("PCI_DEV: ERROR - CanMemBase.");
}
return STATUS_INSUFFICIENT_RESOURCES;
}
//连接中断
if (GotInterrupt)
{
DisablePciInterrupt(pdx);
//连接中断
status = IoConnectInterrupt(
&pdx->pInterruptObject,
(PKSERVICE_ROUTINE)OnInterrupt,
(PVOID)pdx,
NULL,
vector,
IrqL,
IrqL,
mode,
irqshare,
affinity,
FALSE);
if (!NT_SUCCESS(status))
{ //连接不成功处理
pdx->pInterruptObject = NULL;
return status;
}
else
{ //重新使能PCI中断
if (pdx->pInterruptObject == NULL)
{
DbgPrint("Interrupt object is NULL.");
}
KeSynchronizeExecution(pdx->pInterruptObject,(PKSYNCHRONIZE_ROUTINE)EnablePciInterrupt,pdx);
}
}
else
{
MmUnmapIoSpace(pdx->MemBase,pdx->MemCount);
MmUnmapIoSpace(pdx->PdcMemBase,pdx->PdcMemCount);
pdx->pInterruptObject = NULL;
}
pdx->GotResource=TRUE;
return STATUS_SUCCESS;
}