关于多个设备共享一个物理中断的问题。
嘿嘿,以前在论坛看过paul,chao关于共享中断的一些回帖,刚才在看wifi驱动的时候也看到了,现在发个帖子探讨一下。
看了一下MSDN,一目了然,就是不知道具体如何实现的。
Installable ISRs and Device Drivers
Send Feedback
Installable interrupt service routines (ISRs) allow multiple devices to share interrupts and to share a single hardware platform interrupt request (IRQ). ISRs also extend the ability of the OS to process the device in the ISR in addition to the interrupt service thread (IST). If you want to allow interrupt sharing, you should update the ISRs for your device driver. If an installable ISR must recognize the device generating the input, you can usually use the generic installable ISR sample, GIISR.dll.
Because most devices indicate interrupt activity in a single register that is possibly masked, the sample installable ISR handler, GIISR.dll, is adequate for many devices. If necessary, you can write a custom installable ISR handler to implement complex interrupt detection.
You might choose to install an ISR to handle interrupts for the device. This is required if the interrupt is shared between two or more devices, which is a common occurrence with PCI devices. The installed ISR can be a generic routine that simply checks to see if the device is the one requesting service, or it can be a custom design. Giisr.dll is the generic installable ISR. If the IsrHandler and IsrDll values are provided in the device's registry key, then the driver should load the ISR DLL through the LoadIntChainHandler call.
After the ISR is loaded with LoadIntChainHandler, GIISR_INFO, defined in Giisr.h, is filled in and passed to the ISR through KernelLibIoControl with IOCTL_GIISR_INFO. The interrupt handler is unloaded with FreeIntChainHandler.
The following code example shows how to load the ISR DLL with LoadIntChainHandler.
#include <mkfuncs.h>#include <giisr.h>// InstallIsr is a flag that indicates that there is an ISR to be installed.// IsrDll is the ISR DLL name, obtained from the registry.// IsrHandler is the ISR function name, obtained from the registry.// IfcType is the bus interface type, obtained from the registry.// BusNumber is the PCI bus number, obtained from the registry.// Install ISR handler if there is one.if (InstallIsr) { // Install ISR handler g_IsrHandle = LoadIntChainHandler(IsrDll, IsrHandler, (BYTE)Irq); if (!g_IsrHandle) { DEBUGMSG(ZONE_ERROR, (L"WAVEDEV: Couldn't install ISR handler\r\n")); } else { GIISR_INFO Info; PVOID PhysAddr; DWORD inIoSpace = 1; // io space PHYSICAL_ADDRESS PortAddress = {ulIoBase, 0}; if (!TransBusAddrToStatic(PCIBus, 0, PortAddress, ulIoLen, &inIoSpace, &PhysAddr)) { DEBUGMSG(ZONE_ERROR, (L"WAVEDEV: Failed TransBusAddrToStatic\r\n")); return FALSE; } DEBUGMSG(ZONE_PDD, (L"WAVEDEV: Installed ISR handler, Dll = '%s', Handler = '%s', Irq = %d, PhysAddr = 0x%x\r\n", IsrDll, IsrHandler, Irq, PhysAddr)); // Set up ISR handler Info.SysIntr = ulSysIntr; Info.CheckPort = TRUE; Info.PortIsIO = TRUE; Info.UseMaskReg = FALSE; Info.PortAddr = (DWORD)PhysAddr + ES1371_dSTATUS_OFF; Info.PortSize = sizeof(DWORD); Info.Mask = ES1371_INTSTAT_PENDING; if (!KernelLibIoControl(g_IsrHandle, IOCTL_GIISR_INFO, &Info, sizeof(Info), NULL, 0, NULL)) { DEBUGMSG(ZONE_ERROR, (L"WAVEDEV: KernelLibIoControl call failed.\r\n")); } }}