阅读:1920回复:0
请教一PCI驱动中断的问题。。。。。程序如下 // rs4Device.cpp // // Generated by DriverWizard 3.2.0 (Build 2485) // Requires DDK and DriverWorks // File created on 1/2/2003 // // This source file contains the implementation of a subclass of KDevice. // WDM drivers implement a subclass of KPnpDevice and override member // functions to handle requests (IRPs) from the system. // #include <vdw.h> #include "rs4Driver.h" #include "rs4Device.h" #include "..\\intrface.h" #pragma hdrstop("rs4.pch") // Global driver trace object // TODO: Use KDebugOnlyTrace if you want trace messages // to appear only in checked builds. Use KTrace if // you want trace messages to always appear. Call // method SetOutputLevel to set the output threshold. extern KDebugOnlyTrace T; /////////////////////////////////////////////////////////////////////////////////////////////////// // rs4Device::rs4Device // This is the constructor for the class representing the Functional // Device Object, or FDO. It is derived from KPnpDevice, which builds // in automatic dispatching of subfunctions of IRP_MJ_POWER and IRP_MJ_PNP // to virtual member functions. // The object being constructed contains a data member (m_Lower) of type // KPnpLowerDevice. By initializing it, the driver binds the FDO to the // PDO and creates an interface to the upper edge of the system class driver. // // Arguments: // IN Pdo // Physical Device Object. This is a pointer to a system // device object that represents the physical device. // // IN Unit // Unit number to append to the device's base device name // to distinguish multiple units of this device type. // // Return Value: // none // rs4Device::rs4Device(PDEVICE_OBJECT Pdo, ULONG Unit) : m_PciConfig(NULL), KPnpDevice(Pdo, NULL) { if (!NT_SUCCESS(m_ConstructorStatus)) { T.Trace(TraceError, __FUNCTION__": Failed to create device rs4Device" " unit number %d status %x\n", Unit, m_ConstructorStatus); ASSERT(FALSE); return; } // Initialize the lower device m_Lower.Initialize(this, Pdo); // Inform the base class of the lower edge device object SetLowerDevice(&m_Lower); // Initialize the PnP Policy settings to the "standard" policy SetPnpPolicy(); // TODO: Customize the PnP Policy for this device by setting // flags in m_Policies. // Initialize the Power Policy settings to the "standard" policy SetPowerPolicy(); // TODO: Customize the Power Policy for this device by setting // flags in m_PowerPolicies. } /////////////////////////////////////////////////////////////////////////////////////////////////// // rs4Device::~rs4Device // This is the destructor for the class. // // Arguments: // none // // Return Value: // none // rs4Device::~rs4Device() { } /////////////////////////////////////////////////////////////////////////////////////////////////// // rs4Device::DefaultPnp // Default handler for IRP_MJ_PNP. // This routine just passes the IRP through to the lower device. IRPs // that correspond to any virtual members of KpnpDevice that handle // minor functions of IRP_MJ_PNP and that are not overridden get // passed to this routine. // // Arguments: // IN I // the plug and play IRP // // Return Value: // NTSTATUS // Result returned from lower device // NTSTATUS rs4Device::DefaultPnp(KIrp I) { T.Trace(TraceInfo, __FUNCTION__"++. IRP %p\n", I); T << I; I.ForceReuseOfCurrentStackLocationInCalldown(); NTSTATUS status = m_Lower.PnpCall(this, I); T.Trace(TraceInfo, __FUNCTION__"--. IRP %p, STATUS %x\n", I, status); return status; } /////////////////////////////////////////////////////////////////////////////////////////////////// // rs4Device::DefaultPower // Default handler for IRP_MJ_POWER. // This routine just passes the IRP through to the lower device. IRPs // that correspond to any virtual members of KpnpDevice that handle // minor functions of IRP_MJ_POWER and that are not overridden get // passed to this routine. // // Arguments: // IN I // the power IRP // // Return Value: // NTSTATUS // Result returned from lower device // NTSTATUS rs4Device::DefaultPower(KIrp I) { T.Trace(TraceInfo, __FUNCTION__"++. IRP %p\n", I); T << I; I.IndicatePowerIrpProcessed(); I.CopyParametersDown(); NTSTATUS status = m_Lower.PnpPowerCall(this, I); T.Trace(TraceInfo, __FUNCTION__"--. IRP %p, STATUS %x\n", I, status); return status; } /////////////////////////////////////////////////////////////////////////////////////////////////// // rs4Device::SystemControl // Default handler for IRP_MJ_SYSTEM_CONTROL. // This routine just passes the IRP through to the next device since // this driver is not a WMI provider. // // Arguments: // IN I // the system control (WMI) IRP // // Return Value: // NTSTATUS // Result returned from lower device // NTSTATUS rs4Device::SystemControl(KIrp I) { T.Trace(TraceInfo, __FUNCTION__"++. IRP %p\n", I); T << I; NTSTATUS status = STATUS_SUCCESS; I.ForceReuseOfCurrentStackLocationInCalldown(); status = m_Lower.PnpCall(this, I); T.Trace(TraceInfo, __FUNCTION__"--. IRP %p, STATUS %x\n", I, status); return status; } /////////////////////////////////////////////////////////////////////////////////////////////////// // rs4Device::OnStartDevice // Handler for IRP_MJ_PNP subfcn IRP_MN_START_DEVICE. // Initialize the hardware device. Typically, the driver initializes // physical resources here. Call I.AllocatedResources() for a list // of the raw resources that the system has assigned to the device, // or I.TranslatedResources() for the translated resource list. // // Arguments: // IN I // the start device IRP // // Return Value: // NTSTATUS // NTSTATUS rs4Device::OnStartDevice(KIrp I) { T.Trace(TraceInfo, __FUNCTION__"++. IRP %p\n", I); NTSTATUS status = STATUS_SUCCESS; I.Information() = 0; // Get the list of raw resources from the IRP PCM_RESOURCE_LIST pResListRaw = I.AllocatedResources(); // Get the list of translated resources from the IRP PCM_RESOURCE_LIST pResListTranslated = I.TranslatedResources(); // Initialize an instance of KPciConfiguration so we can access // PCI configuration space. m_PciConfig.Initialize(m_Lower.TopOfStack()); do { // For each memory mapped region, initialize the memory mapped range // using the resources provided by the system. Once initialized, each memory // range's base virtual address in system space can be obtained by calling // member Base(). Each memory range's physical address in CPU space can // obtained by calling CpuPhysicalAddress(). To access the memory mapped // range use member functions such as inb/outb, or the array element operator. // TODO: Verify that the variable is assigned the correct PCI BAR. status = m_MemoryRange0.Initialize( pResListTranslated, pResListRaw, 0 ); if (!NT_SUCCESS(status)) { T.Trace(TraceWarning,__FUNCTION__" Failed to initialize m_MemoryRange0 STATUS %x\n", status); break; } status = m_MemoryRange1.Initialize( pResListTranslated, pResListRaw, 1 ); if (!NT_SUCCESS(status)) { T.Trace(TraceWarning,__FUNCTION__" Failed to initialize m_MemoryRange1 STATUS %x\n", status); break; } // For each I/O port mapped region, initialize the I/O port range using the // resources provided by the system. Once initialized, use member functions // such as inb/outb, or the array element operator to access the ports range. // TODO: Verify that the variable is assigned the correct PCI BAR. status = m_IoPortRange0.Initialize( pResListTranslated, pResListRaw, 0 ); if (!NT_SUCCESS(status)) { T.Trace(TraceWarning,__FUNCTION__" Failed to initialize m_IoPortRange0 STATUS %x\n", status); break; } // TODO: Make sure that interrupts are disabled on the hardware // Initialize the interrupt resource and connect the ISR to the interrupt resource status = m_rs4Interrupt.InitializeAndConnect( pResListTranslated, LinkTo(Isr), this ); if (!NT_SUCCESS(status)) { T.Trace(TraceWarning,__FUNCTION__" Failed to initialize m_rs4Interrupt STATUS %x\n", status); break; } // Setup the Deferred Procedure Call (DPC) to be used for interrupt processing m_rs4IsrDpc.Setup(LinkTo(IsrDpc), this); } while (FALSE); if (!NT_SUCCESS(status)) { Invalidate(); return status; } else { // TODO: Add PCI device-specific code to start the hardware. } T.Trace(TraceInfo, __FUNCTION__"--. IRP %p, STATUS %x\n", I, status); return status; } /////////////////////////////////////////////////////////////////////////////////////////////////// // rs4Device::OnStopDevice // Handler for IRP_MJ_PNP subfcn IRP_MN_STOP_DEVICE. // The system calls this when the device is stopped. Release any // hardware resources in this routine. // // Arguments: // IN I // the stop device IRP // // Return Value: // NTSTATUS // NTSTATUS rs4Device::OnStopDevice(KIrp I) { T.Trace(TraceInfo, __FUNCTION__"++. IRP %p\n", I); NTSTATUS status = STATUS_SUCCESS; // TODO: Add device-specific code to stop your hardware device. // The base class will handle completion of the IRP // Release the system resources m_rs4Interrupt.Disconnect(); //使 KInterrupt类实例断开并无效 Invalidate(); T.Trace(TraceInfo, __FUNCTION__"--. IRP %p, STATUS %x\n", I, STATUS_SUCCESS); // Can't fail this IRP return STATUS_SUCCESS; } /////////////////////////////////////////////////////////////////////////////////////////////////// // rs4Device::OnRemoveDevice // Handler for IRP_MJ_PNP subfcn IRP_MN_REMOVE_DEVICE. // 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 // // Arguments: // IN I // the remove device IRP // // Return Value: // NTSTATUS // NTSTATUS rs4Device::OnRemoveDevice(KIrp I) { T.Trace(TraceInfo, __FUNCTION__"++. IRP %p\n", I); NTSTATUS status = STATUS_SUCCESS; // TODO: Add device-specific code to remove your hardware device. // The base class will handle completion of the IRP // Release the system resources m_rs4Interrupt.Disconnect(); //使 KInterrupt类实例断开并无效 Invalidate(); T.Trace(TraceInfo, __FUNCTION__"--. IRP %p, STATUS %x\n", I, STATUS_SUCCESS); // Can't fail this IRP return STATUS_SUCCESS; } /////////////////////////////////////////////////////////////////////////////////////////////////// // rs4Device::OnDevicePowerUp // Handler for IRP_MJ_POWER subfcn IRP_MN_SET_POWER // for a request to go to power on state from low power state // This function was called by the framework from the completion // routine of the IRP_MJ_POWER dispatch handler in KPnpDevice. // The bus driver has completed the IRP and this driver can now // access the hardware device. // This routine runs at DISPATCH_LEVEL. // // Arguments: // IN I // the power IRP // // Return Value: // NTSTATUS // NTSTATUS rs4Device::OnDevicePowerUp(KIrp I) { T.Trace(TraceInfo, __FUNCTION__"++. IRP %p\n", I); NTSTATUS status = STATUS_SUCCESS; // TODO: Add device-specific code to: // Restore any context to the hardware device that // was saved during the handling of a power down request. // See the OnDeviceSleep function. // Do NOT complete this IRP. // The base class will handle completion of the IRP // TODO: Enable interrupts on the hardware T.Trace(TraceInfo, __FUNCTION__"--. IRP %p, STATUS %x\n", I, status); return status; } /////////////////////////////////////////////////////////////////////////////////////////////////// // rs4Device::OnDeviceSleep // Handler for IRP_MJ_POWER subfcn IRP_MN_SET_POWER // for a request to go to a low power state from a high power state // This function was called by the framework from the IRP_MJ_POWER // dispatch handler in KPnpDevice prior to forwarding to the PDO. // The hardware has yet to be powered down and this driver can now // access the hardware device. // This routine runs at PASSIVE_LEVEL. // // Arguments: // IN I // the power IRP // // Return Value: // NTSTATUS // NTSTATUS rs4Device::OnDeviceSleep(KIrp I) { T.Trace(TraceInfo, __FUNCTION__"++. IRP %p\n", I); NTSTATUS status = STATUS_SUCCESS; // TODO: Add device-specific code to: // Save any context to the hardware device that will be required // during a power up request. See the OnDevicePowerUp function. // Do NOT complete this IRP. The base class handles forwarding // this IRP to the PDO. // TODO: Disable interrupts on the hardware T.Trace(TraceInfo, __FUNCTION__"--. IRP %p, STATUS %x\n", I, status); return status; } /////////////////////////////////////////////////////////////////////////////////////////////////// // rs4Device::Create // Dispatch routine for IRP_MJ_CREATE requests. // // Arguments: // IN I // the create IRP // // Return Value: // NTSTATUS // NTSTATUS rs4Device::Create(KIrp I) { T.Trace(TraceInfo, __FUNCTION__"++. IRP %p\n", I); // TODO: For any IRP, to display the contents of the IRP // in a formatted way, use the KTrace << operator: // T << I; NTSTATUS status = STATUS_SUCCESS; // TODO: At this point, perform custom processing for IRP_MJ_CREATE // Generally a create IRP is targeted at our FDO, so its not needed // to pass it down to the PDO. I.Information() = 0; I.PnpComplete(this, status); T.Trace(TraceInfo, __FUNCTION__"--. IRP %p, STATUS %x\n", I, status); return status; } /////////////////////////////////////////////////////////////////////////////////////////////////// // rs4Device::Close // Dispatch routine for IRP_MJ_CLOSE requests. // // Arguments: // IN I // the close IRP // // Return Value: // NTSTATUS // NTSTATUS rs4Device::Close(KIrp I) { T.Trace(TraceInfo, __FUNCTION__"++. IRP %p\n", I); NTSTATUS status = STATUS_SUCCESS; // TODO: At this point, perform custom processing for IRP_MJ_CLOSE // Generally a close IRP is targeted at our FDO, so we don't need // to pass it down to the PDO. I.Information() = 0; I.PnpComplete(this, status); T.Trace(TraceInfo, __FUNCTION__"--. IRP %p, STATUS %x\n", I, status); return status; } /////////////////////////////////////////////////////////////////////////////////////////////////// // rs4Device::Read // Dispatch routine for IRP_MJ_READ requests. // // Arguments: // IN I // the read IRP // // Return Value: // NTSTATUS // NTSTATUS rs4Device::Read(KIrp I) { T.Trace(TraceInfo, __FUNCTION__"++. IRP %p\n", I); NTSTATUS status = STATUS_SUCCESS; // TODO: Validate the parameters of the IRP. Replace "FALSE" // in the following line with error checking code that // evaulates to TRUE if the request is not valid. if (FALSE) { status = STATUS_INVALID_PARAMETER; I.Information() = 0; I.PnpComplete(status); T.Trace(TraceWarning, __FUNCTION__"--. IRP %p, STATUS %x\n", I, status); return status; } // Always ok to read 0 elements if (I.ReadSize() == 0) { I.Information() = 0; I.PnpComplete(this, status); T.Trace(TraceInfo, __FUNCTION__"--. IRP %p, STATUS %x\n", I, status); return status; } KMemory Mem(I.Mdl()); // Declare a memory object // Get a pointer to the caller's buffer. Note that this // routine is safe on all platforms. PUCHAR pBuffer = (PUCHAR) Mem.MapToSystemSpace(); ULONG readSize = I.ReadSize(); ULONG bytesRead = 0; ULONG Data = 0; int n ; for (n =0; n< i ; n ++) { *pBuffer = *(PNUM-i+n); pBuffer++; } I.Information() = (ULONG)1; I.Status() = status; I.PnpComplete(this, status); T.Trace(TraceInfo, __FUNCTION__"--. IRP %p, STATUS %x\n", I, status); return status; } /////////////////////////////////////////////////////////////////////////////////////////////////// // rs4Device::Write // Dispatch routine for IRP_MJ_WRITE requests. // // Arguments: // IN I // the write IRP // // Return Value: // NTSTATUS // NTSTATUS rs4Device::Write(KIrp I) { T.Trace(TraceInfo, __FUNCTION__"++. IRP %p\n", I); NTSTATUS status = STATUS_SUCCESS; // TODO: Validate the parameters of the IRP. Replace "FALSE" // in the following line with error checking code that // evaulates to TRUE if the request is not valid. if (FALSE) { status = STATUS_INVALID_PARAMETER; I.Information() = 0; I.PnpComplete(status); T.Trace(TraceWarning, __FUNCTION__"--. IRP %p, STATUS %x\n", I, status); return status; } // Always ok to write 0 elements if (I.WriteSize() == 0) { I.Information() = 0; I.PnpComplete(this, status); T.Trace(TraceInfo, __FUNCTION__"--. IRP %p, STATUS %x\n", I, status); return status; } //m_MemoryRange1.outd(0xC8,0x02); KMemory Mem(I.Mdl()); // Declare a memory object // Get a pointer to the caller's buffer. Note that this // routine is safe on all platforms. PUCHAR pBuffer = (PUCHAR) Mem.MapToSystemSpace(); ULONG writeSize = I.WriteSize(); ULONG bytesSent = 0; ULONG channelNum = 0; ULONG Data = 0; channelNum = (ULONG)(*pBuffer); pBuffer ++; Data = (ULONG)(*pBuffer); switch(channelNum) { case (ULONG)0x10: if (((m_MemoryRange1.inb((ULONG)0x5c))&0x01) == (UCHAR)0x01) { I.Information() = (ULONG)0; I.Status() = status; } else { m_MemoryRange1.outd(channelNum,&Data,(ULONG)1); I.Information() = (ULONG)2; I.Status() = status; } break; case (ULONG)0x30: if (((m_MemoryRange1.inb((ULONG)0x5c))&0x02) == (UCHAR)0x02) { I.Information() = (ULONG)0; I.Status() = status; } else { m_MemoryRange1.outd(channelNum,&Data,(ULONG)1); I.Information() = (ULONG)2; I.Status() = status; } break; case (ULONG)0x50: if (((m_MemoryRange1.inb((ULONG)0x5c))&0x04) == (UCHAR)0x04) { I.Information() = (ULONG)0; I.Status() = status; } else { m_MemoryRange1.outd(channelNum,&Data,(ULONG)1); I.Information() = (ULONG)2; I.Status() = status; } break; case (ULONG)0x70: if (((m_MemoryRange1.inb((ULONG)0x5c))&0x08) == (UCHAR)0x08) { I.Information() = (ULONG)0; I.Status() = status; } else { m_MemoryRange1.outd(channelNum,&Data,(ULONG)1); I.Information() = (ULONG)2; I.Status() = status; } break; case (ULONG)0x90: if (((m_MemoryRange1.inb((ULONG)0x5c))&0x10) ==(UCHAR)0x10) { I.Information() = (ULONG)0; I.Status() = status; } else { m_MemoryRange1.outd(channelNum,&Data,(ULONG)1); I.Information() = (ULONG)2; I.Status() = status; } break; case (ULONG)0xB0: if (((m_MemoryRange1.inb((ULONG)0x5c))&0x20) == (UCHAR)0x20) { I.Information() = (ULONG)0; I.Status() = status; } else { m_MemoryRange1.outd(channelNum,&Data,(ULONG)1); I.Information() = (ULONG)2; I.Status() = status; } break; case (ULONG)0xD0: if (((m_MemoryRange1.inb((ULONG)0x5c))&(0x40)) == (UCHAR)0x40) { I.Information() = (ULONG)0; I.Status() = status; } else { m_MemoryRange1.outd(channelNum,&Data,(ULONG)1); I.Information() = (ULONG)2; I.Status() = status; } break; case (ULONG)0xF0: if (((m_MemoryRange1.inb((ULONG)0x5C)) & (0x80))==0x80) { I.Information() = (ULONG)0; I.Status() = status; } else { m_MemoryRange1.outd(channelNum,&Data,(ULONG)1); I.Information() = (ULONG)2; I.Status() = status; } break; default: { m_MemoryRange1.outd(channelNum,&Data,(ULONG)1); I.Information() = (ULONG)2; I.Status() = status; } break; } I.PnpComplete(this, status); T.Trace(TraceInfo, __FUNCTION__"--. IRP %p, STATUS %x\n", I, status); return status; } /////////////////////////////////////////////////////////////////////////////////////////////////// // rs4Device::DeviceControl // Dispatch routine for IRP_MJ_DEVICE_CONTROL requests. // // Arguments: // IN I // the ioctl IRP // // Return Value: // NTSTATUS // NTSTATUS rs4Device::DeviceControl(KIrp I) { T.Trace(TraceInfo, __FUNCTION__"++. IRP %p\n", I); NTSTATUS status = STATUS_SUCCESS; switch (I.IoctlCode()) { case 0: { } default: status = STATUS_INVALID_DEVICE_REQUEST; 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) { I.PnpComplete(this, status); } T.Trace(TraceInfo, __FUNCTION__"--. IRP %p, STATUS %x\n", I, status); return status; } /////////////////////////////////////////////////////////////////////////////////////////////////// // rs4Device::CleanUp // Dispatch routine for IRP_MJ_CLEANUP requests. // // Arguments: // IN I // the cleanup IRP // // Return Value: // NTSTATUS // NTSTATUS rs4Device::CleanUp(KIrp I) { T.Trace(TraceInfo, __FUNCTION__"++. IRP %p\n", I); NTSTATUS status = STATUS_SUCCESS; // TODO: At this point, perform custom processing for IRP_MJ_CLEANUP I.PnpComplete(this, status); T.Trace(TraceInfo, __FUNCTION__"--. IRP %p, STATUS %x\n", I, status); return status; } /////////////////////////////////////////////////////////////////////////////////////////////////// // rs4Device::Isr // Interrupt Service Routine (ISR). Minimal processing may be done // here in the ISR, but most processing should be deferred to a DPC. // This routine is called at DEVICE IRQL that is higher than // DISPATCH_LEVEL. // // Arguments: // none // // Return Value: // BOOLEAN TRUE if this is our interrupt // BOOLEAN rs4Device::Isr(void) { // TODO: Test if the Interrupt was from our hardware device. // Replace "TRUE" in next line with actual test. //2008.08.29 #define mask_int_9030 0x00000004 #define clear_int_9030 0x00000400 #define default_int_9030 0x00000043 ULONG Offset_9030 = 0x4C, temp; #if 1 temp=m_MemoryRange0.ind(Offset_9030); if ((temp&mask_int_9030) ==0) { // Return FALSE to indicate that this device did not cause the interrupt. return FALSE; } //temp=m_MemoryRange0.ind(Offset_9030)|clear_int_9030; //m_MemoryRange0.outd(Offset_9030,temp); // m_MemoryRange0.outd(Offset_9030,0x00000000); // m_MemoryRange0.outd(Offset_9030,default_int_9030); if (!m_rs4IsrDpc.Request(NULL, NULL)) { // TODO: The DPC 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 #endif return TRUE; // TODO: Service the device. // Minimal processing may be done here in the ISR, but // most processing should be deferred to a DPC. // Generally, you should: // o stop the device from generating interrupts // 0 get the reason for the interrupt (DMA done, read complete, // write complete, other operation complete) // o perform any additional time-critical functions // o schedule a DPC to perform the bulk of the work. // RS4_ISR_REASON reason = IsrReasonNone; // Request deferred procedure call (DPC) // TODO: The arguments to Request may be any values that you choose // Perhaps the reason for the interrupt } /////////////////////////////////////////////////////////////////////////////////////////////////// // rs4Device::IsrDpc // Deferred Procedure Call (DPC). // 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. // This routine executes at DISPATCH_LEVEL. // // Arguments: // IN Arg1 // User-defined context variable passed from Isr() // // IN Arg2 // User-defined context variable passed from Isr() // // Return Value: // none // VOID rs4Device::IsrDpc(PVOID Arg1, PVOID Arg2) { //RS4_ISR_REASON reason = (RS4_ISR_REASON)(ULONG_PTR) Arg1; ULONG Data = 0; i=0; while((m_MemoryRange1.ind((ULONG)0x1C) &0x02)==0x02) { m_MemoryRange1.ind((ULONG)0x34,&Data ,(ULONG)1); *PNUM = (ULONG)0X34; PNUM ++; i++; *PNUM = (UCHAR)(Data & 0x000000ff); PNUM ++; i++; } // TODO: Typically, the interrupt signals the end of a data transfer // operation for a READ or WRITE or IOCTL operation. If this is // the case, add code to handle the completion of the IRP // associated with this operation here. // The following macros simply allows compilation at Warning Level 4 // If you reference these parameters in the function simply remove the macro. // UNREFERENCED_PARAMETER(Arg1); // UNREFERENCED_PARAMETER(Arg2); } /////////////////////////////////////////////////////////////////////////////////////////////////// // rs4Device::Invalidate // This method performs resource cleanup. // This function is called from OnStopDevice, OnRemoveDevice and // OnStartDevice (in error conditions). It calls the Invalidate // member funcitons for each resource to free the underlying system // resource if allocated. It is safe to call Invalidate more than // once for a resource, or for an uninitialized resource. // // Arguments: // none // // Return Value: // none // VOID rs4Device::Invalidate() { NTSTATUS status = STATUS_SUCCESS; // TODO: Disable interrupts on the hardware before doing this. // Disconnet the Interrupt Service Routine (ISR) from the interrupt object m_rs4Interrupt.Invalidate(); // For each I/O port mapped region, unmap the memory associated with it. m_IoPortRange0.Invalidate(); // For each memory mapped region, unmap the memory associated with it. m_MemoryRange0.Invalidate(); m_MemoryRange1.Invalidate(); } 装上后运行write 程序时就蓝屏, 有时候死机, 很是恼火, 中断估计是写的不对, 求那位高人指点一下啊, 或者可以在延迟程序DPC里面调用读的程序, 可是不晓得要怎么写, 也拜托告知一下, 万分感谢了 |
|