📄 pcidpprivate.c
字号:
//*****************************************************************************
// THIS CODE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
// OR IMPLIED. THIS CODE IS COPYRIGHTED AND MAY NOT BE MODIFIED OR DISTRIBUTED
// WITHOUT THE WRITTEN CONSENT OF THE PRODUCER.
//
// Copyright (C) 2002, Foxen Solutions
// Copyright (C) 2002, FXN
//
// All Rights Reserved.
//*****************************************************************************
//
//
// This is PCIDPPrivate.c. It contains those routines whose access status
// is private within the PCIDP kernel driver.
#include "PCIDPInc.h"
#include "PCIDP.h"
NTSTATUS StartDevice(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
){
NTSTATUS NTStatus;
BOOLEAN Status;
ULONG LIdx;
ULONG DIdx;
CM_RESOURCE_LIST* Resources;
MEMORY_CACHING_TYPE CacheType;
KINTERRUPT_MODE InterruptMode;
BOOLEAN Shareable;
KIRQL InterruptLevel;
PIO_STACK_LOCATION IrpStack;
PPCIDP_EXTENSION ObjExt = (PPCIDP_EXTENSION)DeviceObject->DeviceExtension;
// Debug entry point
//DbgPrint("[PCIDP]->Entering StartDevice...\n"); //debug
//DbgBreakPoint(); //debug
IoSetDeviceInterfaceState(&ObjExt->SymbolicLinkName, TRUE);
// Let the lower level drivers handle the IRP first.
IoCopyCurrentIrpStackLocationToNext(IN Irp);
IoSetCompletionRoutine(
IN Irp,
IN DeviceCompletionRoutine,
IN NULL, //Context
IN TRUE, //InvokeOnSuccess
IN TRUE, //InvokeOnError
IN TRUE //InvokeOnCancel
);
NTStatus = IoCallDriver(ObjExt->NextLowerDeviceObject, Irp);
if(NTStatus == STATUS_PENDING){
KeWaitForSingleObject(
IN &ObjExt->WaitEvent,
IN Executive, //WaitReason
IN KernelMode, //WaitMode
IN FALSE, //Alertable
IN NULL //Timeout
);
NTStatus = Irp->IoStatus.Status;
}
// Processed after the lower level drivers have successfully finished with the IRP.
if(NT_SUCCESS(NTStatus)){
IrpStack = IoGetCurrentIrpStackLocation(IN Irp);
Resources = IrpStack->Parameters.StartDevice.AllocatedResourcesTranslated;
// Get the I/O port attributes.
Status = GetResources(Resources, CmResourceTypePort, &LIdx, &DIdx);
if(Status == TRUE){
ObjExt->IOAccess = Resources->List[LIdx].PartialResourceList.PartialDescriptors[DIdx].u.Port.Start;
ObjExt->IOAccessLength = Resources->List[LIdx].PartialResourceList.PartialDescriptors[DIdx].u.Port.Length;
}
else{
//ObjExt->IOAccess = 0;
ObjExt->IOAccessLength = 0;
NTStatus = STATUS_INSUFFICIENT_RESOURCES;
//Irp->IoStatus.Status = NTStatus;
return NTStatus;
}
// Map to the memory base space in order to support driver services.
Status = GetResources(Resources, CmResourceTypeMemory, &LIdx, &DIdx);
if(Status == TRUE){
if(
Resources->List[LIdx].PartialResourceList.PartialDescriptors[DIdx].Flags &
CM_RESOURCE_MEMORY_COMBINEDWRITE
)
CacheType = MmWriteCombined;
else if(
Resources->List[LIdx].PartialResourceList.PartialDescriptors[DIdx].Flags &
CM_RESOURCE_MEMORY_CACHEABLE
)
CacheType = MmCached;
else
CacheType = MmNonCached;
ObjExt->MemoryAccess = Resources->List[LIdx].PartialResourceList.PartialDescriptors[DIdx].u.Memory.Start;
ObjExt->MemoryAccessLength = Resources->List[LIdx].PartialResourceList.PartialDescriptors[DIdx].u.Memory.Length;
ObjExt->MemoryBase = (ULONG*)MmMapIoSpace(
IN ObjExt->MemoryAccess,
IN ObjExt->MemoryAccessLength,
IN CacheType
);
if(ObjExt->MemoryBase == NULL){
NTStatus = STATUS_SOME_NOT_MAPPED;
//Irp->IoStatus.Status = NTStatus;
return NTStatus;
}
}
else{
NTStatus = STATUS_INSUFFICIENT_RESOURCES;
//Irp->IoStatus.Status = NTStatus;
return NTStatus;
}
// Map the PCI board's IRQ to a system vector.
// todo: resolve the interrupt pin source
ObjExt->InterruptObject = 0;
//if((ULONG)CardInfo.u.type0.InterruptPin != 0){ //use IRP_MN_READ_CONFIG
// Connect the driver to the IRQ.
Status = GetResources(Resources, CmResourceTypeInterrupt, &LIdx, &DIdx);
if(Status == TRUE){
if(
Resources->List[LIdx].PartialResourceList.PartialDescriptors[DIdx].Flags ==
CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE
)
InterruptMode = LevelSensitive;
else
InterruptMode = Latched;
if(
Resources->List[LIdx].PartialResourceList.PartialDescriptors[DIdx].ShareDisposition ==
CmResourceShareShared
)
Shareable = TRUE;
else
Shareable = FALSE;
InterruptLevel = (KIRQL)Resources->List[LIdx].PartialResourceList.PartialDescriptors[DIdx].u.Interrupt.Level;
NTStatus = IoConnectInterrupt(
OUT &ObjExt->InterruptObject,
IN PCIDPISR, //pointer to ISR
IN DeviceObject, //context to send to ISR
IN NULL, //optional spinlock
IN Resources->List[LIdx].PartialResourceList.PartialDescriptors[DIdx].u.Interrupt.Vector, //mapped interrupt vector
IN InterruptLevel, //DIRQL u.Interrupt.Level
IN InterruptLevel, //DIRQL u.Interrupt.Level
IN InterruptMode, //latched/level interrupt
IN Shareable, //shareable interrupt
IN Resources->List[LIdx].PartialResourceList.PartialDescriptors[DIdx].u.Interrupt.Affinity, //processor enable mask
IN FALSE //floating save (false for X86)
);
if(NTStatus != STATUS_SUCCESS){
ObjExt->InterruptObject = 0;
//Irp->IoStatus.Status = NTStatus;
return NTStatus;
}
// Register the PCIDPForDpcIsr routine with this device
// driver.
IoInitializeDpcRequest(
IN DeviceObject,
IN PCIDPForDpcIsr
);
// Set up the spin lock for the linked list holding pending IRPs.
KeInitializeSpinLock(&ObjExt->LListSpin);
}
//}
}
// Debug exit point
//DbgPrint("[PCIDP]->Leaving StartDevice, status=0x%x...\n", NTStatus); //debug
//DbgBreakPoint(); //debug
return NTStatus;
}
NTSTATUS StopDevice(IN PDEVICE_OBJECT DeviceObject){
PPCIDP_EXTENSION ObjExt = (PPCIDP_EXTENSION)DeviceObject->DeviceExtension;
// Debug entry point
//DbgPrint("[PCIDP]->Entering StopDevice...\n"); //debug
//DbgBreakPoint(); //debug
// Disconnect the driver from the interrupt if enabled.
if(ObjExt->InterruptObject)
IoDisconnectInterrupt(ObjExt->InterruptObject);
// Delete all allocated entries in the linked list.
DeleteAllEntries(ObjExt);
// Unmap physical memory.
MmUnmapIoSpace(ObjExt->MemoryBase, ObjExt->MemoryAccessLength);
return STATUS_SUCCESS;
}
NTSTATUS CancelStopDevice(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
){
NTSTATUS NTStatus;
PPCIDP_EXTENSION ObjExt = (PPCIDP_EXTENSION)DeviceObject->DeviceExtension;
// Debug entry point
//DbgPrint("[PCIDP]->Entering CancelStopDevice...\n"); //debug
//DbgBreakPoint(); //debug
// Let the lower level drivers handle the IRP first.
IoCopyCurrentIrpStackLocationToNext(IN Irp);
IoSetCompletionRoutine(
IN Irp,
IN DeviceCompletionRoutine,
IN NULL, //Context
IN TRUE, //InvokeOnSuccess
IN TRUE, //InvokeOnError
IN TRUE //InvokeOnCancel
);
NTStatus = IoCallDriver(ObjExt->NextLowerDeviceObject, Irp);
if(NTStatus == STATUS_PENDING){
KeWaitForSingleObject(
IN &ObjExt->WaitEvent,
IN Executive, //WaitReason
IN KernelMode, //WaitMode
IN FALSE, //Alertable
IN NULL //Timeout
);
NTStatus = Irp->IoStatus.Status;
}
// Debug exit point
//DbgPrint("[PCIDP]->Leaving CancelStopDevice, status=0x%x...\n", NTStatus); //debug
//DbgBreakPoint(); //debug
return NTStatus;
}
NTSTATUS RemoveDevice(IN PDEVICE_OBJECT DeviceObject){
PPCIDP_EXTENSION ObjExt = (PPCIDP_EXTENSION)DeviceObject->DeviceExtension;
// Debug entry point
//DbgPrint("[PCIDP]->Entering RemoveDevice...\n"); //debug
//DbgBreakPoint(); //debug
// Free up DMA contiguous memory.
MmUnlockPages(ObjExt->MDL);
IoFreeMdl(ObjExt->MDL);
MmFreeContiguousMemory(ObjExt->VirtualDMAAddress);
RtlFreeUnicodeString(&ObjExt->SymbolicLinkName);
IoDetachDevice(ObjExt->NextLowerDeviceObject);
IoDeleteDevice(DeviceObject);
return STATUS_SUCCESS;
}
NTSTATUS DeviceCompletionRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
){
PPCIDP_EXTENSION ObjExt = (PPCIDP_EXTENSION)DeviceObject->DeviceExtension;
KeSetEvent(&ObjExt->WaitEvent, IO_NO_INCREMENT, FALSE);
return STATUS_MORE_PROCESSING_REQUIRED;
}
BOOLEAN GetResources(
CM_RESOURCE_LIST* Resources,
UCHAR CmResourceType,
ULONG* pLIdx,
ULONG* pDIdx
){
ULONG LIdx;
ULONG DIdx;
ULONG PRLCount;
BOOLEAN Found = FALSE;
// Debug entry point
//DbgPrint("[PCIDP]->Entering GetResources...\n"); //debug
//DbgBreakPoint(); //debug
for(LIdx=0; LIdx<Resources->Count; LIdx++){
PRLCount = Resources->List[LIdx].PartialResourceList.Count;
for(DIdx=0; DIdx<PRLCount; DIdx++){
if(
Resources->List[LIdx].PartialResourceList.PartialDescriptors[DIdx].Type ==
CmResourceType
){
//DbgPrint("[PCIDP]->&Resources: 0x%x...\n", &Resources->List[LIdx].PartialResourceList.PartialDescriptors[DIdx]); //debug
//DbgBreakPoint(); //debug
Found = TRUE;
break;
}
}
if(Found == TRUE)
break;
}
*pLIdx = LIdx;
*pDIdx = DIdx;
return Found;
}
// These routines are the linked list utilities. They protect the linked list
// with a spin lock, limiting access to one thread at a time. The linked list
// contains those pending IRPs.
BOOLEAN GetNextEntry(
PPCIDP_EXTENSION ObjExt,
PLINKED_LIST* FirstLink,
PLINKED_LIST* CurrentLink,
PREGISTERED_INTERRUPT* Entry
){
BOOLEAN Status = FALSE;
KIRQL LListIrql;
PLINKED_LIST CurrentLnk;
KeAcquireSpinLock(&ObjExt->LListSpin, &LListIrql);
if(*FirstLink == NULL){
if(ObjExt->LLData.InsertedCount > 0){
*FirstLink = ObjExt->LLData.CurrentLink;
*CurrentLink = *FirstLink;
CurrentLnk = *CurrentLink;
if(CurrentLnk->Status == LL_INSERTED){
CurrentLnk->Status = LL_CHECKEDOUT;
ObjExt->LLData.InsertedCount--;
*Entry = &(CurrentLnk->RegisteredInterrupt);
Status = TRUE;
goto GetNextExit;
}
}
}
if(*FirstLink != NULL){
CurrentLnk = *CurrentLink;
CurrentLnk = CurrentLnk->Next;
while(CurrentLnk != *FirstLink){
if(CurrentLnk->Status == LL_INSERTED){
CurrentLnk->Status = LL_CHECKEDOUT;
ObjExt->LLData.InsertedCount--;
*Entry = &(CurrentLnk->RegisteredInterrupt);
Status = TRUE;
break;
}
CurrentLnk = CurrentLnk->Next;
}
*CurrentLink = CurrentLnk;
}
GetNextExit:
//ObjExt->MemoryBase[0x1C57] = ObjExt->LLData.InsertedCount; //debug
KeReleaseSpinLock(&ObjExt->LListSpin, LListIrql);
return Status;
}
BOOLEAN PutBackEntry(PPCIDP_EXTENSION ObjExt, PLINKED_LIST CurrentLink){
BOOLEAN Status;
KIRQL LListIrql;
KeAcquireSpinLock(&ObjExt->LListSpin, &LListIrql);
if(CurrentLink->Status == LL_CHECKEDOUT){
CurrentLink->Status = LL_INSERTED;
ObjExt->LLData.InsertedCount++;
Status = TRUE;
}
else
Status = FALSE;
KeReleaseSpinLock(&ObjExt->LListSpin, LListIrql);
//ObjExt->MemoryBase[0x1C57] = ObjExt->LLData.InsertedCount;//debug
//ObjExt->MemoryBase[0x1C58]++;//debug
return Status;
}
BOOLEAN FreeEntry(PPCIDP_EXTENSION ObjExt, PLINKED_LIST CurrentLink){
BOOLEAN Status;
KIRQL LListIrql;
KeAcquireSpinLock(&ObjExt->LListSpin, &LListIrql);
if(CurrentLink->Status == LL_CHECKEDOUT || CurrentLink->Status == LL_ACQUIRED){
CurrentLink->Status = LL_AVAILABLE;
ObjExt->LLData.CurrentLink = CurrentLink->Prev;
Status = TRUE;
}
else
Status = FALSE;
KeReleaseSpinLock(&ObjExt->LListSpin, LListIrql);
//ObjExt->MemoryBase[0x1C59]++;//debug
return Status;
}
PLINKED_LIST GetFreeEntry(PPCIDP_EXTENSION ObjExt){
PLINKED_LIST FirstLink;
PLINKED_LIST ReturnLink = NULL;
KIRQL LListIrql;
KeAcquireSpinLock(&ObjExt->LListSpin, &LListIrql);
if(ObjExt->LLData.IsEmpty == FALSE) {
FirstLink = ObjExt->LLData.CurrentLink;
do{
ObjExt->LLData.CurrentLink = ObjExt->LLData.CurrentLink->Next;
if(ObjExt->LLData.CurrentLink->Status == LL_AVAILABLE){
ObjExt->LLData.CurrentLink->Status = LL_ACQUIRED;
ReturnLink = ObjExt->LLData.CurrentLink;
//ObjExt->MemoryBase[0x1C65]++; //debug
break;
}
} while(FirstLink != ObjExt->LLData.CurrentLink);
}
KeReleaseSpinLock(&ObjExt->LListSpin, LListIrql);
if(ReturnLink == NULL){
ReturnLink = ExAllocatePool(NonPagedPool, sizeof(LINKED_LIST));
if(ReturnLink != NULL){
ReturnLink->Status = LL_NEW;
//ObjExt->MemoryBase[0x1C64]++; //debug
}
}
return ReturnLink;
}
BOOLEAN InsertEntry(PPCIDP_EXTENSION ObjExt, PLINKED_LIST Entry){
BOOLEAN Status = TRUE;
PLINKED_LIST CurrentLink;
KIRQL LListIrql;
KeAcquireSpinLock(&ObjExt->LListSpin, &LListIrql);
if(Entry->Status == LL_NEW){
Entry->Status = LL_INSERTED;
ObjExt->LLData.FreeMax++;
ObjExt->LLData.InsertedCount++;
if(ObjExt->LLData.IsEmpty == TRUE) {
Entry->Prev = Entry;
Entry->Next = Entry;
ObjExt->LLData.CurrentLink = Entry;
ObjExt->LLData.IsEmpty = FALSE;
//ObjExt->MemoryBase[0x1C66]++; //debug
}
else {
CurrentLink = ObjExt->LLData.CurrentLink;
Entry->Prev = CurrentLink;
Entry->Next = CurrentLink->Next;
CurrentLink->Next->Prev = Entry;
CurrentLink->Next = Entry;
//ObjExt->MemoryBase[0x1C67]++; //debug
}
}
else if(Entry->Status == LL_ACQUIRED){
Entry->Status = LL_INSERTED;
ObjExt->LLData.InsertedCount++;
//ObjExt->MemoryBase[0x1C68]++; //debug
}
else
Status = FALSE;
KeReleaseSpinLock(&ObjExt->LListSpin, LListIrql);
//ObjExt->MemoryBase[0x1C5A] = ObjExt->LLData.FreeMax;//debug
//ObjExt->MemoryBase[0x1C57] = ObjExt->LLData.InsertedCount;//debug
return Status;
}
BOOLEAN DeleteAllEntries(PPCIDP_EXTENSION ObjExt){
PLINKED_LIST CurrentLink = ObjExt->LLData.CurrentLink;
while(ObjExt->LLData.IsEmpty == FALSE) {
if(CurrentLink->Status == LL_INSERTED)
ObjExt->LLData.InsertedCount--;
if(CurrentLink->Next == CurrentLink) {
ObjExt->LLData.IsEmpty = TRUE;
}
else {
CurrentLink->Prev->Next = CurrentLink->Next;
CurrentLink->Next->Prev = CurrentLink->Prev;
CurrentLink = CurrentLink->Prev;
}
ObjExt->LLData.FreeMax--;
//ObjExt->MemoryBase[0x1C5A] = ObjExt->LLData.FreeMax;//debug
//ObjExt->MemoryBase[0x1C57] = ObjExt->LLData.InsertedCount;//debug
ExFreePool(ObjExt->LLData.CurrentLink);
}
return(!ObjExt->LLData.IsEmpty);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -