📄 pcidp.c
字号:
break;
case IOCTL_PCIDP00_GET_PCI_CONFIG_REGS:
PCIDPGetPCIRegs(
IN DeviceObject,
IN IrpStack->FileObject,
IN OUT Irp,
OUT IoBuffer,
IN OutputBufferLength
);
break;
case IOCTL_PCIDP00_SET_PCI_CONFIG_REGS:
PCIDPSetPCIRegs(
IN DeviceObject,
IN IrpStack->FileObject,
IN OUT Irp,
IN IoBuffer,
IN InputBufferLength
);
break;
case IOCTL_PCIDP00_REGISTER_INTERRUPT:
PCIDPRegisterInterrupt(
IN DeviceObject,
IN OUT Irp,
IN IoBuffer,
IN InputBufferLength,
IN OutputBufferLength
);
break;
case IOCTL_PCIDP00_UNREGISTER_INTERRUPT:
PCIDPUnregisterInterrupt(
IN DeviceObject,
IN OUT Irp,
IN IoBuffer,
IN InputBufferLength
);
break;
case IOCTL_PCIDP00_HELLO:
break;
case IOCTL_PCIDP00_GET_VERSION:
PCIDPGetDriverVersion(
IN OUT Irp,
OUT IoBuffer,
IN OutputBufferLength
);
break;
default:
Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
break;
}
// Finish the I/O operation by simply completing the packet and returning
// the same status as in the packet itself. However, don't complete the I/O
// if the status is pending (register interrupt only).
NTStatus = Irp->IoStatus.Status;
if(NTStatus != STATUS_PENDING)
IoCompleteRequest(Irp, IO_NO_INCREMENT);
// Debug exit point
if(NTStatus != STATUS_PENDING)
//DbgPrint("[PCIDP]->Leaving DeviceControl, status=0x%x...\n", NTStatus); //debug
//DbgBreakPoint(); //debug
return NTStatus;
}
// ----------------------------------------------------------------------------
// PCIDPCreateClose. Called by the I/O system when the device is opened or
// closed. No action is currently performed other than completing the request
// successfully.
// ----------------------------------------------------------------------------
NTSTATUS PCIDPCreateClose(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
){
// Debug entry point
//DbgPrint("[PCIDP]->Entering CreateClose...\n"); //debug
//DbgBreakPoint(); //debug
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest( Irp, IO_NO_INCREMENT );
return STATUS_SUCCESS;
}
// ----------------------------------------------------------------------------
// PCIDPCleanup. Called by the system when a file object handle representing
// the device is being released. Cancel any pending interrupts assigned to
// the file handle.
// ----------------------------------------------------------------------------
NTSTATUS PCIDPCleanup(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
){
// Define variables.
PPCIDP_EXTENSION ObjExt;
PREGISTERED_INTERRUPT Interrupt;
PIO_STACK_LOCATION CleanUpStack ;
PIO_STACK_LOCATION IrpStack ;
KIRQL CancelSpin;
PLINKED_LIST CurrentLink;
PLINKED_LIST FirstLink;
// Debug entry point
//DbgPrint("[PCIDP]->Entering Cleanup...\n"); //debug
//DbgBreakPoint(); //debug
// Initialize variables.
ObjExt = (PPCIDP_EXTENSION)DeviceObject->DeviceExtension;
// Search the driver's events linked list for an entry containing the
// user provided Irp.
CleanUpStack = IoGetCurrentIrpStackLocation(Irp);
CurrentLink = NULL;
FirstLink = NULL;
while(GetNextEntry(ObjExt, &FirstLink, &CurrentLink, &Interrupt) == TRUE){
IrpStack = IoGetCurrentIrpStackLocation(Interrupt->Irp);
// Cancel the IRP, then delete its linked list entry.
if (IrpStack->FileObject == CleanUpStack->FileObject) {
IoAcquireCancelSpinLock (&CancelSpin);
Interrupt->Irp->Cancel = TRUE;
//Interrupt->Irp->CancelIrql = CancelSpin;
Interrupt->Irp->CancelRoutine = NULL;
Interrupt->Irp->IoStatus.Status = STATUS_CANCELLED;
Interrupt->Irp->IoStatus.Information = 0;
IoReleaseCancelSpinLock (CancelSpin);
IoReleaseCancelSpinLock (Interrupt->Irp->CancelIrql);
IoCompleteRequest(Interrupt->Irp, IO_NO_INCREMENT);
FreeEntry(ObjExt, CurrentLink);
}
else
PutBackEntry(ObjExt, CurrentLink);
}
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
// ----------------------------------------------------------------------------
// PCIDPUnload. Called by the I/O system when unloading the driver. No action
// is currently performed.
// ----------------------------------------------------------------------------
NTSTATUS PCIDPUnload(
IN PDRIVER_OBJECT DriverObject
){
// Debug entry point
//DbgPrint("[PCIDP]->Entering Unload...\n"); //debug
//DbgBreakPoint(); //debug
return STATUS_SUCCESS;
}
// ----------------------------------------------------------------------------
// PCIDPCancelInterrupt. Called when an IRP for an interrupt must be canceled
// normally due to a system shutdown.
// ----------------------------------------------------------------------------
VOID PCIDPCancelInterrupt(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp
){
// Define variables.
PPCIDP_EXTENSION ObjExt;
PREGISTERED_INTERRUPT Interrupt;
PLINKED_LIST CurrentLink;
PLINKED_LIST FirstLink;
// Debug entry point
//DbgPrint("[PCIDP]->Entering CancelInterrupt...\n"); //debug
//DbgBreakPoint(); //debug
// Initialize variables.
ObjExt = (PPCIDP_EXTENSION)DeviceObject->DeviceExtension;
// Search the driver's events linked list for an entry containing the
// user provided Irp.
CurrentLink = NULL;
FirstLink = NULL;
while(GetNextEntry(ObjExt, &FirstLink, &CurrentLink, &Interrupt) == TRUE){
// Delete its linked list entry.
if(Irp == Interrupt->Irp){
FreeEntry(ObjExt, CurrentLink);
break;
}
else
PutBackEntry(ObjExt, CurrentLink);
}
//IoReleaseCancelSpinLock (Irp->CancelIrql);
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_CANCELLED;
IoCompleteRequest(Irp, IO_NO_INCREMENT) ;
}
// ----------------------------------------------------------------------------
// PCIDPForDpcIsr. Deferred procedure call for the interrupt service routine.
// ----------------------------------------------------------------------------
VOID PCIDPForDpcIsr(
IN PKDPC Dpc,
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
){
// Define variables.
PPCIDP_EXTENSION ObjExt;
PINTERRUPT_DATA IntData;
PREGISTERED_INTERRUPT RegisteredInt;
KIRQL CancelSpin;
PLINKED_LIST CurrentLink;
PLINKED_LIST FirstLink;
// Debug
//PULONG MemoryBase;
// Initialize variables.
ObjExt = (PPCIDP_EXTENSION)DeviceObject->DeviceExtension;
IntData = &ObjExt->InterruptData;
// Debug
//MemoryBase = ObjExt->MemoryBase;
//MemoryBase[0x1C53]++;
//Service all of the recorded interrupts by checking to see if the interrupt
//type has been registered by the user.
while(IntData->QueNew != IntData->QueNext){
// Debug
//MemoryBase[0x1C54]++;
CurrentLink = NULL;
FirstLink = NULL;
while(GetNextEntry(ObjExt, &FirstLink, &CurrentLink, &RegisteredInt) == TRUE){
// Debug
//MemoryBase[0x1C55]++;
if(IntData->Type[IntData->QueNew] == RegisteredInt->Type){
// Debug
//MemoryBase[0x1C56]++;
// Found an entry. Disable the cancel routine, complete the I/O for
// this IRP, then delete the linked list entry.
IoAcquireCancelSpinLock (&CancelSpin);
IoSetCancelRoutine(RegisteredInt->Irp, NULL);
IoReleaseCancelSpinLock (CancelSpin);
RegisteredInt->Irp->IoStatus.Status = STATUS_SUCCESS ;
RegisteredInt->Irp->IoStatus.Information = 0 ;
IoCompleteRequest(RegisteredInt->Irp, IO_NO_INCREMENT);
FreeEntry(ObjExt, CurrentLink);
}
else
PutBackEntry(ObjExt, CurrentLink);
}
IntData->QueNew++;
if(IntData->QueNew == InterruptQueSize) IntData->QueNew = 0;
}
}
// ----------------------------------------------------------------------------
// PCIDPISR. Interrupt service routine.
// ----------------------------------------------------------------------------
BOOLEAN PCIDPISR(
IN PKINTERRUPT Interrupt,
IN OUT PVOID Context
){
// Define variables.
BOOLEAN Status;
PDEVICE_OBJECT DeviceObject;
PPCIDP_EXTENSION ObjExt;
PINTERRUPT_DATA IntData;
PULONG MemoryBase;
ULONG HINTStatusReg;
// Check the masked HINT for an active interrupt. If it's not set,
// the PCIDP card did not cause the interrupt, so exit quick.
DeviceObject = (PDEVICE_OBJECT)Context;
ObjExt = (PPCIDP_EXTENSION)DeviceObject->DeviceExtension;
MemoryBase = ObjExt->MemoryBase;
// Debug
//MemoryBase[0x1C50]++;
HINTStatusReg = MemoryBase[HINT] & 0x03FF;
if(HINTStatusReg == 0){
// Debug
//MemoryBase[0x1C51]++;
Status = FALSE;
goto ExitA;
}
// Initialize variables.
DeviceObject = (PDEVICE_OBJECT)Context;
IntData = &ObjExt->InterruptData;
// This board caused the interrupt. Now determine what type of interrupt
// was triggered.
if(HINTStatusReg & PCIMasterAbort){
IntData->Type[IntData->QueNext] = PCIMasterAbort;
IntData->QueNext++;
if(IntData->QueNext == InterruptQueSize) IntData->QueNext = 0;
}
if(HINTStatusReg & PCITargetAbort){
IntData->Type[IntData->QueNext] = PCITargetAbort;
IntData->QueNext++;
if(IntData->QueNext == InterruptQueSize) IntData->QueNext = 0;
}
if(HINTStatusReg & I2OOutboundPostFIFONotEmpty){
IntData->Type[IntData->QueNext] = I2OOutboundPostFIFONotEmpty;
IntData->QueNext++;
if(IntData->QueNext == InterruptQueSize) IntData->QueNext = 0;
}
if(HINTStatusReg & DMAComplete){
IntData->Type[IntData->QueNext] = DMAComplete;
IntData->QueNext++;
if(IntData->QueNext == InterruptQueSize) IntData->QueNext = 0;
// Debug
//MemoryBase[0x1C52]++;
}
if(HINTStatusReg & LocalToHostExternalSignal){
IntData->Type[IntData->QueNext] = LocalToHostExternalSignal;
IntData->QueNext++;
if(IntData->QueNext == InterruptQueSize) IntData->QueNext = 0;
}
if(HINTStatusReg & LocalToHostMailbox){
IntData->Type[IntData->QueNext] = LocalToHostMailbox;
IntData->QueNext++;
if(IntData->QueNext == InterruptQueSize) IntData->QueNext = 0;
}
if(HINTStatusReg & I2OPCIFIFOOverflow){
IntData->Type[IntData->QueNext] = I2OPCIFIFOOverflow;
IntData->QueNext++;
if(IntData->QueNext == InterruptQueSize) IntData->QueNext = 0;
}
// Clear all set interrupts as indicated in the status part of the
// HINT register while preserving the enabled part of the HINT. This
// is done by writing a 1 to each active bit which just happens to
// be value in HINTStatusReg.
MemoryBase[HINT] |= HINTStatusReg;
// Lastly, request the defered interrupt handler be queued for processing.
IoRequestDpc(DeviceObject, NULL, NULL);
Status = TRUE;
ExitA:
return Status;
}
// ----------------------------------------------------------------------------
// PCIDPCancelMapDMARoutine. Called when an application that has mapped to DMA
// space fails to unmap from that space.
// ----------------------------------------------------------------------------
VOID PCIDPCancelMapDMARoutine(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp
){
// Define variables.
PPCIDP_EXTENSION ObjExt;
PREGISTERED_INTERRUPT Interrupt;
PLINKED_LIST CurrentLink;
PLINKED_LIST FirstLink;
// Debug entry point
//DbgPrint("[PCIDP]->Entering CancelMapDMARoutine...\n"); //debug
//DbgBreakPoint(); //debug
// Initialize variables.
ObjExt = (PPCIDP_EXTENSION)DeviceObject->DeviceExtension;
//ObjExt->MemoryBase[0x1C5B]++; //debug
// Search the driver's events linked list for an entry containing the
// user provided Irp.
CurrentLink = NULL;
FirstLink = NULL;
while(GetNextEntry(ObjExt, &FirstLink, &CurrentLink, &Interrupt) == TRUE){
//ObjExt->MemoryBase[0x1C5C]++; //debug
// Delete its linked list entry and unmap from DMA space.
if(Irp == Interrupt->Irp){
FreeEntry(ObjExt, CurrentLink);
if(ObjExt->MDL){
MmUnmapLockedPages((PVOID)Interrupt->Type, ObjExt->MDL); //linear address in Type
}
//ObjExt->MemoryBase[0x1C5D]++; //debug
break;
}
else
PutBackEntry(ObjExt, CurrentLink);
}
IoReleaseCancelSpinLock (Irp->CancelIrql);
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_CANCELLED;
IoCompleteRequest(Irp, IO_NO_INCREMENT) ;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -