📄 pcidppublic.c
字号:
PPCIDP_EXTENSION ObjExt;
PMDL Mdl;
PREGISTERED_INTERRUPT RegisteredInt;
KIRQL CancelSpin;
PLINKED_LIST CurrentLink;
PLINKED_LIST FirstLink;
// Initialize variables.
NTStatus = STATUS_SUCCESS;
IoInput = (PPCIDP00_UNMAP_DMA_SEND)IoBuffer;
ObjExt = (PPCIDP_EXTENSION)DeviceObject->DeviceExtension;
if(InputBufferLength >= sizeof(PCIDP00_UNMAP_DMA_SEND)){
if(ObjExt->MDL){
MmUnmapLockedPages((PVOID)IoInput->LinearAddress, ObjExt->MDL);
NTStatus = STATUS_SUCCESS;
//ObjExt->MemoryBase[0x1C61]++; //debug
// Cancel the CancelMapDMA pending irp.
CurrentLink = NULL;
FirstLink = NULL;
while(GetNextEntry(ObjExt, &FirstLink, &CurrentLink, &RegisteredInt) == TRUE){
//ObjExt->MemoryBase[0x1C62]++; //debug
if(IoInput->LinearAddress == RegisteredInt->Type){
// 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);
//IoReleaseCancelSpinLock (RegisteredInt->Irp->CancelIrql);
RegisteredInt->Irp->IoStatus.Status = STATUS_SUCCESS ;
RegisteredInt->Irp->IoStatus.Information = 0 ;
IoCompleteRequest(RegisteredInt->Irp, IO_NO_INCREMENT);
//ObjExt->MemoryBase[0x1C63]++; //debug
FreeEntry(ObjExt, CurrentLink);
}
else
PutBackEntry(ObjExt, CurrentLink);
}
}
else
NTStatus = STATUS_NO_MEMORY;
}
else
NTStatus = STATUS_INVALID_BUFFER_SIZE;
Irp->IoStatus.Status = NTStatus;
}
// ----------------------------------------------------------------------------
// PCIDPGetPCIRegs
// ----------------------------------------------------------------------------
VOID PCIDPGetPCIRegs(
IN PDEVICE_OBJECT DeviceObject,
IN PFILE_OBJECT FileObject,
IN OUT PIRP Irp,
OUT PVOID IoBuffer,
IN ULONG OutputBufferLength
){
// Define variables.
NTSTATUS NTStatus;
PPCIDP_EXTENSION ObjExt;
PIO_STACK_LOCATION NextIrpStack;
// Initialize variables.
ObjExt = (PPCIDP_EXTENSION)DeviceObject->DeviceExtension;
// Check for adequate output buffer space.
if(OutputBufferLength >= sizeof(PCIDP00_GET_PCI_CONFIG_REGS_RECV)){
// Now get the PCI register space.
NextIrpStack = IoGetNextIrpStackLocation(Irp);
NextIrpStack->MajorFunction = IRP_MJ_PNP;
NextIrpStack->MinorFunction = IRP_MN_READ_CONFIG;
NextIrpStack->Flags = 0;
NextIrpStack->Parameters.ReadWriteConfig.WhichSpace = 0;
NextIrpStack->Parameters.ReadWriteConfig.Buffer = IoBuffer;
NextIrpStack->Parameters.ReadWriteConfig.Offset = 0;
NextIrpStack->Parameters.ReadWriteConfig.Length = OutputBufferLength;
NextIrpStack->DeviceObject = ObjExt->NextLowerDeviceObject;
NextIrpStack->FileObject = FileObject;
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
);
}
}
else{
NTStatus = STATUS_INVALID_BUFFER_SIZE;
Irp->IoStatus.Status = NTStatus;
Irp->IoStatus.Information = 0;
}
}
// ----------------------------------------------------------------------------
// PCIDPSetPCIRegs
// ----------------------------------------------------------------------------
VOID PCIDPSetPCIRegs(
IN PDEVICE_OBJECT DeviceObject,
IN PFILE_OBJECT FileObject,
IN OUT PIRP Irp,
IN PVOID IoBuffer,
IN ULONG InputBufferLength
){
// Define variables.
NTSTATUS NTStatus;
PPCIDP_EXTENSION ObjExt;
PIO_STACK_LOCATION NextIrpStack;
// Initialize variables.
ObjExt = (PPCIDP_EXTENSION)DeviceObject->DeviceExtension;
// Check for adequate input buffer space.
if(InputBufferLength >= sizeof(PCIDP00_SET_PCI_CONFIG_REGS_SEND)){
// Now set the PCI register space.
NextIrpStack = IoGetNextIrpStackLocation(Irp);
NextIrpStack->MajorFunction = IRP_MJ_PNP;
NextIrpStack->MinorFunction = IRP_MN_WRITE_CONFIG;
NextIrpStack->Flags = 0;
NextIrpStack->Parameters.ReadWriteConfig.WhichSpace = 0;
NextIrpStack->Parameters.ReadWriteConfig.Buffer = IoBuffer;
NextIrpStack->Parameters.ReadWriteConfig.Offset = 0;
NextIrpStack->Parameters.ReadWriteConfig.Length = InputBufferLength;
NextIrpStack->DeviceObject = ObjExt->NextLowerDeviceObject;
NextIrpStack->FileObject = FileObject;
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
);
}
}
else{
NTStatus = STATUS_INVALID_BUFFER_SIZE;
Irp->IoStatus.Status = NTStatus;
Irp->IoStatus.Information = 0;
}
}
// ----------------------------------------------------------------------------
// PCIDPRegisterInterrupt
// ----------------------------------------------------------------------------
VOID PCIDPRegisterInterrupt(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp,
IN OUT PVOID IoBuffer,
IN ULONG InputBufferLength,
IN ULONG OutputBufferLength
){
// Define variables.
NTSTATUS NTStatus;
PPCIDP00_REGISTER_INTERRUPT_SEND IoInput;
PPCIDP_EXTENSION ObjExt;
KIRQL CancelSpin;
PULONG MemoryBase;
PLINKED_LIST LLEntry;
ULONG Type;
ULONG HINTPattern;
// Initialize variables.
IoInput = (PPCIDP00_REGISTER_INTERRUPT_SEND)IoBuffer;
ObjExt = (PPCIDP_EXTENSION)DeviceObject->DeviceExtension;
MemoryBase = ObjExt->MemoryBase;
// Check that call was made via the PCIDP API.
if((IoInput->InterruptType & 0xF0C00000) != 0xF0C00000){
NTStatus = STATUS_ACCESS_DENIED;
goto ExitA;
}
Type = IoInput->InterruptType & 0x000003FF;
// Check to make sure the board has the interrupt pin enabled.
if(ObjExt->InterruptObject == 0){
NTStatus = STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT;
goto ExitA;
}
// Make sure the buffer lengths are of sufficient size to handle
// the transactions.
if(InputBufferLength < sizeof(PCIDP00_REGISTER_INTERRUPT_SEND)){
NTStatus = STATUS_INVALID_BUFFER_SIZE;
goto ExitA;
}
// Check for a valid interrupt type.
switch(Type){
case PCIMasterAbort:
case PCITargetAbort:
case I2OOutboundPostFIFONotEmpty:
case DMAComplete:
case LocalToHostExternalSignal:
case LocalToHostMailbox:
case I2OPCIFIFOOverflow:
break;
default:
NTStatus = STATUS_INVALID_PARAMETER;
goto ExitA;
}
// Get an empty linked list entry.
LLEntry = GetFreeEntry(ObjExt);
if(LLEntry != NULL){
// Set up a cancel routine and mark the IRP pending.
IoMarkIrpPending (Irp);
IoAcquireCancelSpinLock (&CancelSpin);
IoSetCancelRoutine (Irp, PCIDPCancelInterrupt);
IoReleaseCancelSpinLock (CancelSpin);
// Add this IRP to the linked list
LLEntry->RegisteredInterrupt.Irp = Irp;
LLEntry->RegisteredInterrupt.Type = Type;
InsertEntry(ObjExt, LLEntry);
// Enable the interrupt on the board and clear the status bit.
HINTPattern = MemoryBase[HINT] & 0xFFFF0000; //get enabled ints
HINTPattern |= Type; //bit to clear status
HINTPattern |= (Type << 16); //bit to enable the interrupt
MemoryBase[HINT] = HINTPattern;
// Return with I/O pending.
NTStatus = STATUS_PENDING;
}
else
NTStatus = STATUS_NO_MEMORY;
ExitA:
Irp->IoStatus.Status = NTStatus;
}
// ----------------------------------------------------------------------------
// PCIDPUnRegisterInterrupt
// ----------------------------------------------------------------------------
VOID PCIDPUnregisterInterrupt(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp,
IN OUT PVOID IoBuffer,
IN ULONG InputBufferLength
){
// Define variables.
NTSTATUS NTStatus;
PPCIDP00_UNREGISTER_INTERRUPT_SEND IoInput;
PPCIDP_EXTENSION ObjExt;
KIRQL CancelSpin;
PULONG MemoryBase;
PREGISTERED_INTERRUPT Interrupt;
PIO_STACK_LOCATION ThisIrpStack;
PIO_STACK_LOCATION LLIrpStack;
PLINKED_LIST CurrentLink;
PLINKED_LIST FirstLink;
ULONG Count;
ULONG Type;
// Initialize variables.
IoInput = (PPCIDP00_UNREGISTER_INTERRUPT_SEND)IoBuffer;
ObjExt = (PPCIDP_EXTENSION)DeviceObject->DeviceExtension;
MemoryBase = ObjExt->MemoryBase;
Count = 0;
// Check that call was made via the PCIDP API.
if((IoInput->InterruptType & 0xF0C00000) != 0xF0C00000){
NTStatus = STATUS_ACCESS_DENIED;
goto ExitA;
}
Type = IoInput->InterruptType & 0x000003FF;
// Check to make sure the board has the interrupt pin enabled.
if(ObjExt->InterruptObject == 0){
NTStatus = STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT;
goto ExitA;
}
// Make sure the buffer lengths are of sufficient size to handle
// the transactions.
if(InputBufferLength < sizeof(PCIDP00_REGISTER_INTERRUPT_SEND)){
NTStatus = STATUS_INVALID_BUFFER_SIZE;
goto ExitA;
}
// Check for a valid interrupt type.
switch(Type){
case PCIMasterAbort:
case PCITargetAbort:
case I2OOutboundPostFIFONotEmpty:
case DMAComplete:
case LocalToHostExternalSignal:
case LocalToHostMailbox:
case I2OPCIFIFOOverflow:
break;
default:
NTStatus = STATUS_INVALID_PARAMETER;
goto ExitA;
}
// Search the driver's events linked list for an an entry containing the
// user provided interrupt type.
NTStatus = STATUS_SUCCESS;
ThisIrpStack = IoGetCurrentIrpStackLocation(Irp);
CurrentLink = NULL;
FirstLink = NULL;
while(GetNextEntry(ObjExt, &FirstLink, &CurrentLink, &Interrupt) == TRUE){
if(Type == Interrupt->Type){
Count++;
LLIrpStack = IoGetCurrentIrpStackLocation(Interrupt->Irp);
// Cancel the IRP, then delete its linked list entry.
if (LLIrpStack->FileObject == ThisIrpStack->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);
IoCompleteRequest(Interrupt->Irp, IO_NO_INCREMENT);
FreeEntry(ObjExt, CurrentLink);
}
else
PutBackEntry(ObjExt, CurrentLink);
}
else
PutBackEntry(ObjExt, CurrentLink);
}
// Disable the interrupt type if no other thread is currently
// registered.
if(Count == 1)
MemoryBase[HINT] &= (~Type) << 16;
ExitA:
Irp->IoStatus.Status = NTStatus;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -