📄 pciwdmdevice.cpp
字号:
//
// Comments:
// The system calls this when the device is removed.
// Our PnP policy will take care of
// (1) giving the IRP to the lower device
// (2) detaching the PDO
// (3) deleting the device object
//
NTSTATUS PciwdmDevice::OnRemoveDevice(KIrp I)
{
// Device removed, release the system resources.
Invalidate();
// TODO: Add device-specific code to remove your device
return STATUS_SUCCESS;
// The following macro simply allows compilation at Warning Level 4
// If you reference this parameter in the function simply remove the macro.
UNREFERENCED_PARAMETER(I);
}
////////////////////////////////////////////////////////////////////////
// PciwdmDevice::Create
//
// Routine Description:
// Handler for IRP_MJ_CREATE
//
// Parameters:
// I - Current IRP
//
// Return Value:
// NTSTATUS - Result code
//
// Comments:
//
NTSTATUS PciwdmDevice::Create(KIrp I)
{
NTSTATUS status;
// TODO: Add driver specific create handling code here
// Generally a create IRP is targeted at our FDO, so we don't need
// to pass it down to the PDO. We have found for some devices, the
// PDO is not expecting this Irp and returns an error code.
// The default wizard code, therefore completes the Irp here using
// PnpComplete(). The following commented code could be used instead
// of PnpComplete() to pass the Irp to the PDO, which would complete it.
//
// I.ForceReuseOfCurrentStackLocationInCalldown();
// status = m_Lower.PnpCall(this, I);
if ((PADAPTER_OBJECT)m_DmaAdapter == NULL)
{
Invalidate();
return STATUS_UNSUCCESSFUL;
}
m_DmaBuffer.Initialize(&m_DmaAdapter,4096);
if (m_DmaBuffer.VirtualAddress() == NULL)
{
m_DmaBuffer.Invalidate();
return STATUS_UNSUCCESSFUL;
}
m_PAddr=m_DmaBuffer.LogicalAddress().LowPart;
m_LAddr=m_DmaBuffer.VirtualAddress();
m_IoPortRange0.outd(INTCSR,0x3f0000);
m_IoPortRange0.outd(MWAR,m_PAddr);
m_IoPortRange0.outd(MWTC,fwLength);
m_IoPortRange0.outd(MCSR,0xc000000);
m_IoPortRange0.outd(INTCSR,0x20005000);
status = I.PnpComplete(this, STATUS_SUCCESS, IO_NO_INCREMENT);
return status;
}
////////////////////////////////////////////////////////////////////////
// PciwdmDevice::Close
//
// Routine Description:
// Handler for IRP_MJ_CLOSE
//
// Parameters:
// I - Current IRP
//
// Return Value:
// NTSTATUS - Result code
//
// Comments:
//
NTSTATUS PciwdmDevice::Close(KIrp I)
{
NTSTATUS status;
// TODO: Add driver specific close handling code here
// Generally a close IRP is targeted at our FDO, so we don't need
// to pass it down to the PDO. We have found for some devices, the
// PDO is not expecting this Irp and returns an error code.
// The default wizard code, therefore completes the Irp here using
// PnpComplete(). The following commented code could be used instead
// of PnpComplete() to pass the Irp to the PDO, which would complete it.
//
// I.ForceReuseOfCurrentStackLocationInCalldown();
// status = m_Lower.PnpCall(this, I);
m_IoPortRange0.outd(INTCSR,0);
m_DmaBuffer.Invalidate();
status = I.PnpComplete(this, STATUS_SUCCESS, IO_NO_INCREMENT);
return status;
}
////////////////////////////////////////////////////////////////////////
// PciwdmDevice::DeviceControl
//
// Routine Description:
// Handler for IRP_MJ_DEVICE_CONTROL
//
// Parameters:
// I - Current IRP
//
// Return Value:
// None
//
// Comments:
// This routine is the first handler for Device Control requests.
// The KPnpDevice class handles restricting IRP flow
// if the device is stopping or being removed.
//
NTSTATUS PciwdmDevice::DeviceControl(KIrp I)
{
NTSTATUS status;
switch (I.IoctlCode())
{
case EVENT_REGISTER:
status = EVENT_REGISTER_Handler(I);
m_IoPortRange0.outb(OMB1,0x55);
break;
case READ_DATA:
status = READ_DATA_Handler(I);
break;
default:
// Unrecognized IOCTL request
status = STATUS_INVALID_PARAMETER;
break;
}
// If the IRP's IOCTL handler deferred processing using some driver
// specific scheme, the status variable is set to STATUS_PENDING.
// In this case we simply return that status, and the IRP will be
// completed later. Otherwise, complete the IRP using the status
// returned by the IOCTL handler.
if (status == STATUS_PENDING)
{
return status;
}
else
{
return I.PnpComplete(this, status);
}
}
////////////////////////////////////////////////////////////////////////
// PciwdmDevice::EVENT_REGISTER_Handler
//
// Routine Description:
// Handler for IO Control Code EVENT_REGISTER
//
// Parameters:
// I - IRP containing IOCTL request
//
// Return Value:
// NTSTATUS - Status code indicating success or failure
//
// Comments:
// This routine implements the EVENT_REGISTER function.
// This routine runs at passive level.
//
NTSTATUS PciwdmDevice::EVENT_REGISTER_Handler(KIrp I)
{
HANDLE hEvent;
NTSTATUS status;
// TODO: Verify that the input parameters are correct
// If not, return STATUS_INVALID_PARAMETER
// TODO: Handle the the EVENT_REGISTER request, or
// defer the processing of the IRP (i.e. by queuing) and set
// status to STATUS_PENDING.
// TODO: Assuming that the request was handled here. Set I.Information
// to indicate how much data to copy back to the user.
hEvent = *(HANDLE*)I.IoctlBuffer();
m_pEventToSignal = new(NonPagedPool) KEvent(hEvent);
status = (m_pEventToSignal != NULL) ? STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES;
I.Information() = 0;
return status;
}
////////////////////////////////////////////////////////////////////////
// PciwdmDevice::READ_DATA_Handler
//
// Routine Description:
// Handler for IO Control Code READ_DATA
//
// Parameters:
// I - IRP containing IOCTL request
//
// Return Value:
// NTSTATUS - Status code indicating success or failure
//
// Comments:
// This routine implements the READ_DATA function.
// This routine runs at passive level.
//
NTSTATUS PciwdmDevice::READ_DATA_Handler(KIrp I)
{
NTSTATUS status;
if (I.IoctlOutputBufferSize() >= fwLength)
{
strcpy((PCHAR)I.IoctlBuffer(),(PCHAR)m_LAddr);
I.Information() = fwLength;
status = STATUS_SUCCESS;
}
else
{
I.Information() = 0;
status = STATUS_BUFFER_TOO_SMALL;
}
// TODO: Verify that the input parameters are correct
// If not, return STATUS_INVALID_PARAMETER
// TODO: Handle the the READ_DATA request, or
// defer the processing of the IRP (i.e. by queuing) and set
// status to STATUS_PENDING.
// TODO: Assuming that the request was handled here. Set I.Information
// to indicate how much data to copy back to the user.
return status;
}
////////////////////////////////////////////////////////////////////////
// PciwdmDevice::DpcFor_Irq
//
// Routine Description:
// Deferred Procedure Call (DPC) for Irq
//
// Parameters:
// Arg1 - User-defined context variable
// Arg2 - User-defined context variable
//
// Return Value:
// None
//
// Comments:
// This function is called for secondary processing of an interrupt.
// Most code that runs at elevated IRQL should run here rather than
// in the ISR, so that other interrupt handlers can continue to run.
//
VOID PciwdmDevice::DpcFor_Irq(PVOID Arg1, PVOID Arg2)
{
// TODO: Typically, the interrupt signals the end of a data transfer
// operation for a READ or WRITE operation. If this is the
// case, add code to handle the completion of the IRP
// associated with this operation here.
// TODO: Enable further interrupts on the device.
// The following macros simply allows compilation at Warning Level 4
// If you reference these parameters in the function simply remove the macro.
m_pEventToSignal->Set(); // or Pulse
UNREFERENCED_PARAMETER(Arg1);
UNREFERENCED_PARAMETER(Arg2);
}
////////////////////////////////////////////////////////////////////////
// PciwdmDevice::Isr_Irq
//
// Routine Description:
// Interrupt Service Routine (ISR) for IRQ Irq
//
// Parameters:
// None
//
// Return Value:
// BOOLEAN True if this is our interrupt
//
// Comments:
//
BOOLEAN PciwdmDevice::Isr_Irq(void)
{
unsigned int state,box;
state=m_IoPortRange0.ind(INTCSR);
if ((state&0x800000)!=0x800000) return FALSE;
if ((state&0x20000)==0x20000) {
m_IoPortRange0.outd(INTCSR,state&0xff02ffff);
box=m_IoPortRange0.ind(MBEF);
if ((box&0x10000)==0x10000) {
box=m_IoPortRange0.ind(IMB1);
if (box&0xaa==0xaa) m_IoPortRange0.outd(MCSR,0x700);
T << "DMA Start!\n";
}
}
else if ((state&0x40000)==0x40000) {
m_IoPortRange0.outd(INTCSR,state&0xff04ffff);
m_DpcFor_Irq.Request(NULL, NULL);
}
else if ((state&0x300000)!=0) {
m_IoPortRange0.outd(INTCSR,state&0xff03ffff);
T << "DMA Abort!\n";
}
// if (!m_DpcFor_Irq.Request(NULL, NULL))
// {
// TODO: Request is already in the queue
// You may want to set flags or perform
// other actions in this case
// }
// Return TRUE to indicate that our device caused the interrupt
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -