can not get CmResourceTypePort

Hi, guys
people recommand me to use KMDF driver mode. but i just want to take a try at WDM. Please be patient:)

Here is the code:
PCM_PARTIAL_RESOURCE_DESCRIPTOR resource = &list->PartialDescriptors[0];
ULONG nres = list->Count;
KdPrint((“list->Count=0x%x\n”, nres));
BOOLEAN IsMem0 = TRUE;
for (ULONG i = 0; i < nres; ++i, ++resource)
{ // for each resource
KdPrint((“type=0x%x\n”,resource->Type));
switch (resource->Type)
{ // switch on resource type
case CmResourceTypePort:
portbase = resource->u.Port.Start;
pdx->nports = resource->u.Port.Length;
pdx->mappedport = (resource->Flags & CM_RESOURCE_PORT_IO) == 0;
gotport = TRUE;
break;

case CmResourceTypeMemory:
if (IsMem0)
{
pdx->MemBar0 = (PUCHAR)MmMapIoSpace(resource->u.Memory.Start,
resource->u.Memory.Length,
MmNonCached);
pdx->nMem0 = resource->u.Memory.Length;
IsMem0 = FALSE;
}else
{
pdx->MemBar1 = (PUCHAR)MmMapIoSpace(resource->u.Memory.Start,
resource->u.Memory.Length,
MmNonCached);
pdx->nMem1 = resource->u.Memory.Length;
}

break;

case CmResourceTypeInterrupt:
irql = (KIRQL) resource->u.Interrupt.Level;
vector = resource->u.Interrupt.Vector;
affinity = resource->u.Interrupt.Affinity;
mode = (resource->Flags == CM_RESOURCE_INTERRUPT_LATCHED)
? Latched : LevelSensitive;
irqshare = resource->ShareDisposition == CmResourceShareShared;
gotinterrupt = TRUE;

break;

default:
KdPrint((“Unexpected I/O resource type %d\n”, resource->Type));
break;
} // switch on resource type
} // for each resource

if (!(TRUE&& gotport&& gotinterrupt))
{
KdPrint((" Didn’t get expected I/O resources\n"));
return STATUS_DEVICE_CONFIGURATION_ERROR;
}

The result is :
list->Count = 5, the 5 resource->Type i get are 0x3, 0x81, 0x3, 0x81, 0x2.
0x3: CmResourceTypeMemory
0x81: CmResourceTypePrivate
0x2: CmResourceTypeInterrupt
but there is no information about the CmResourceTypePort. where is the device info in CmResource from? Windows sets the device info automatically or i should set something like CmResourceTypePort? Thanks a lot.

forgive me! some device does not need CmResourceTypePort, is that right?

Plenty of devices don’t have ports, and depending on the platform port
on a device can show up as memory.

Don Burn (MVP, Windows DKD)
Windows Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr

wxhsdp@163.com” wrote in message news:xxxxx@ntdev:

> forgive me! some device does not need CmResourceTypePort, is that right?

wxhsdp@163.com wrote:

forgive me! some device does not need CmResourceTypePort, is that right?

You need to know which resources your device needs. Most PCI devices
use memory. Very few use I/O ports any more.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

another question: except the device itself, xp defaultly enable the pci interrupt on its side, is that right?

wxhsdp@163.com wrote:

another question: except the device itself, xp defaultly enable the pci interrupt on its side, is that right?

The interrupt controller and the PCI bridge configuration is all managed
by the operating system.

the only thing i need to do is active the IRQ pin A, and on the path from interrupt controller to cpu, there is nothing stop me by default, is that right?

Once you call IoConnectInterrupt, the path from your device to the
processor is ready to go. If your device asserts an interrupt, your ISR
will be called. Things remain in that state until you call
IoDisconnectInterrupt.

now i turn to WDM mode, everything seems to be right. i can see my pci device in device manager, and i use IRPTrace to see the conditions when i start my device. the start device IRP is OK, with interrupt connected right…but ISR is not entered when i assert the interrupt, what’s the problem? on the path from interrupt controller to the CPU, is there anything stop me? what about the local APIC and IO APIC? In BIOS i can see all the IRQs are enabled.

The APIC is managed by the operating system. If you have connected the
interrupt properly, then your ISR will be called. Why don’t you show us
your IRP_MN_START_DEVICE handler?


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

here is the code, it’s from an example, thanks!
#pragma INITCODE
extern “C” NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject,
IN PUNICODE_STRING pRegistryPath)
{
KdPrint((“Enter DriverEntry\n”));

pDriverObject->DriverExtension->AddDevice = HelloWDMAddDevice;
pDriverObject->MajorFunction[IRP_MJ_PNP] = HelloWDMPnp;
pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchControl;
pDriverObject->MajorFunction[IRP_MJ_CREATE] =
pDriverObject->MajorFunction[IRP_MJ_CLOSE] =
pDriverObject->MajorFunction[IRP_MJ_READ] =
pDriverObject->MajorFunction[IRP_MJ_WRITE] = HelloWDMDispatchRoutine;
pDriverObject->DriverUnload = HelloWDMUnload;

KdPrint((“Leave DriverEntry\n”));
return STATUS_SUCCESS;
}

#pragma PAGEDCODE
NTSTATUS HelloWDMAddDevice(IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject)
{
PAGED_CODE();
KdPrint((“Enter HelloWDMAddDevice\n”));

NTSTATUS status;
PDEVICE_OBJECT fdo;
status = IoCreateDevice(
DriverObject,
sizeof(DEVICE_EXTENSION),
NULL,
FILE_DEVICE_UNKNOWN,
0,
FALSE,
&fdo);
if( !NT_SUCCESS(status))
return status;
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)fdo->DeviceExtension;
pdx->fdo = fdo;
pdx->NextStackDevice = IoAttachDeviceToDeviceStack(fdo, PhysicalDeviceObject);

status = IoRegisterDeviceInterface(PhysicalDeviceObject, &MY_WDM_DEVICE, NULL, &pdx->interfaceName);
if(!NT_SUCCESS(status))
{
IoDeleteDevice(fdo);
return status;
}
KdPrint((“%wZ\n”,&pdx->interfaceName));
IoSetDeviceInterfaceState(&pdx->interfaceName, TRUE);

if(!NT_SUCCESS(status))
{
if( !NT_SUCCESS(status))
{
return status;
}
}

fdo->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;
fdo->Flags &= ~DO_DEVICE_INITIALIZING;

KdPrint((“Leave HelloWDMAddDevice\n”));
return STATUS_SUCCESS;
}

NTSTATUS HelloWDMPnp(IN PDEVICE_OBJECT fdo,
IN PIRP Irp)
{
PAGED_CODE();

KdPrint((“Enter HelloWDMPnp\n”));
NTSTATUS status = STATUS_SUCCESS;
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
static NTSTATUS (*fcntab)(PDEVICE_EXTENSION pdx, PIRP Irp) =
{
HandleStartDevice, // IRP_MN_START_DEVICE
DefaultPnpHandler, // IRP_MN_QUERY_REMOVE_DEVICE
HandleRemoveDevice, // IRP_MN_REMOVE_DEVICE
DefaultPnpHandler, // IRP_MN_CANCEL_REMOVE_DEVICE
DefaultPnpHandler, // IRP_MN_STOP_DEVICE
DefaultPnpHandler, // IRP_MN_QUERY_STOP_DEVICE
DefaultPnpHandler, // IRP_MN_CANCEL_STOP_DEVICE
DefaultPnpHandler, // IRP_MN_QUERY_DEVICE_RELATIONS
DefaultPnpHandler, // IRP_MN_QUERY_INTERFACE
DefaultPnpHandler, // IRP_MN_QUERY_CAPABILITIES
DefaultPnpHandler, // IRP_MN_QUERY_RESOURCES
DefaultPnpHandler, // IRP_MN_QUERY_RESOURCE_REQUIREMENTS
DefaultPnpHandler, // IRP_MN_QUERY_DEVICE_TEXT
DefaultPnpHandler, // IRP_MN_FILTER_RESOURCE_REQUIREMENTS
DefaultPnpHandler, //
DefaultPnpHandler, // IRP_MN_READ_CONFIG
DefaultPnpHandler, // IRP_MN_WRITE_CONFIG
DefaultPnpHandler, // IRP_MN_EJECT
DefaultPnpHandler, // IRP_MN_SET_LOCK
DefaultPnpHandler, // IRP_MN_QUERY_ID
DefaultPnpHandler, // IRP_MN_QUERY_PNP_DEVICE_STATE
DefaultPnpHandler, // IRP_MN_QUERY_BUS_INFORMATION
DefaultPnpHandler, // IRP_MN_DEVICE_USAGE_NOTIFICATION
DefaultPnpHandler, // IRP_MN_SURPRISE_REMOVAL
};

ULONG fcn = stack->MinorFunction;
if (fcn >= arraysize(fcntab))
{
status = DefaultPnpHandler(pdx, Irp); // some function we don’t know about
return status;
}

#if DBG
static char* fcnname =
{
“IRP_MN_START_DEVICE”,
“IRP_MN_QUERY_REMOVE_DEVICE”,
“IRP_MN_REMOVE_DEVICE”,
“IRP_MN_CANCEL_REMOVE_DEVICE”,
“IRP_MN_STOP_DEVICE”,
“IRP_MN_QUERY_STOP_DEVICE”,
“IRP_MN_CANCEL_STOP_DEVICE”,
“IRP_MN_QUERY_DEVICE_RELATIONS”,
“IRP_MN_QUERY_INTERFACE”,
“IRP_MN_QUERY_CAPABILITIES”,
“IRP_MN_QUERY_RESOURCES”,
“IRP_MN_QUERY_RESOURCE_REQUIREMENTS”,
“IRP_MN_QUERY_DEVICE_TEXT”,
“IRP_MN_FILTER_RESOURCE_REQUIREMENTS”,
“”,
“IRP_MN_READ_CONFIG”,
“IRP_MN_WRITE_CONFIG”,
“IRP_MN_EJECT”,
“IRP_MN_SET_LOCK”,
“IRP_MN_QUERY_ID”,
“IRP_MN_QUERY_PNP_DEVICE_STATE”,
“IRP_MN_QUERY_BUS_INFORMATION”,
“IRP_MN_DEVICE_USAGE_NOTIFICATION”,
“IRP_MN_SURPRISE_REMOVAL”,
};

KdPrint((“PNP Request (%s)\n”, fcnname[fcn]));
#endif // DBG

status = (*fcntab[fcn])(pdx, Irp);
KdPrint((“Leave HelloWDMPnp\n”));
return status;
}

#pragma PAGEDCODE
NTSTATUS HandleStartDevice(PDEVICE_EXTENSION pdx, PIRP Irp)
{
PAGED_CODE();
KdPrint((“Enter HandleStartDevice\n”));

NTSTATUS status = ForwardAndWait(pdx,Irp);
if (!NT_SUCCESS(status))
{
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}

PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);

PCM_PARTIAL_RESOURCE_LIST translated;
if (stack->Parameters.StartDevice.AllocatedResourcesTranslated)
translated = &stack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0].PartialResourceList;
else
translated = NULL;

KdPrint((“translated=0x%x\n”, (int)translated));
KdPrint((“Init the PCI card!\n”));
InitMyPCI(pdx,translated);

Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);

KdPrint((“Leave HandleStartDevice\n”));
return status;
}

#pragma PAGEDCODE
NTSTATUS InitMyPCI(IN PDEVICE_EXTENSION pdx,IN PCM_PARTIAL_RESOURCE_LIST list)
{
PDEVICE_OBJECT fdo = pdx->fdo;

ULONG vector;
KIRQL irql;
KINTERRUPT_MODE mode;
KAFFINITY affinity;
BOOLEAN irqshare;
BOOLEAN gotinterrupt = FALSE;

PHYSICAL_ADDRESS portbase;
BOOLEAN gotport = FALSE;

PCM_PARTIAL_RESOURCE_DESCRIPTOR resource = &list->PartialDescriptors[0];
ULONG nres = list->Count;
KdPrint((“list->Count=0x%x\n”, nres));
BOOLEAN IsMem0 = TRUE;
for (ULONG i = 0; i < nres; ++i, ++resource)
{
KdPrint((“type=0x%x\n”,resource->Type));
switch (resource->Type)
{ case CmResourceTypePort:
portbase = resource->u.Port.Start;
pdx->nports = resource->u.Port.Length;
pdx->mappedport = (resource->Flags & CM_RESOURCE_PORT_IO) == 0;
gotport = TRUE;
break;

case CmResourceTypeMemory:
if (IsMem0)
{
pdx->MemBar0 = (PUCHAR)MmMapIoSpace(resource->u.Memory.Start, resource->u.Memory.Length, MmNonCached);
pdx->nMem0 = resource->u.Memory.Length;
IsMem0 = FALSE;
}else
{
pdx->MemBar1 = (PUCHAR)MmMapIoSpace(resource->u.Memory.Start, resource->u.Memory.Length, MmNonCached);
pdx->nMem1 = resource->u.Memory.Length;
}

break;

case CmResourceTypeInterrupt:
irql = (KIRQL) resource->u.Interrupt.Level;
vector = resource->u.Interrupt.Vector;
affinity = resource->u.Interrupt.Affinity;
mode = (resource->Flags == CM_RESOURCE_INTERRUPT_LATCHED) ? Latched : LevelSensitive;
irqshare = resource->ShareDisposition == CmResourceShareShared;
gotinterrupt = TRUE;

break;

default:
KdPrint((“Unexpected I/O resource type %d\n”, resource->Type));
break;
}
}
/*
if (!(TRUE&& gotport&& gotinterrupt))
{
KdPrint((" Didn’t get expected I/O resources\n"));
return STATUS_DEVICE_CONFIGURATION_ERROR;
}
*/
if (!(TRUE&& gotinterrupt))
{
KdPrint((" Didn’t get expected I/O resources\n"));
return STATUS_DEVICE_CONFIGURATION_ERROR;
}

if (pdx->mappedport)
{
pdx->portbase = (PUCHAR) MmMapIoSpace(portbase, pdx->nports, MmNonCached);
if (!pdx->mappedport)
{
KdPrint((“Unable to map port range %I64X, length %X\n”, portbase, pdx->nports));
return STATUS_INSUFFICIENT_RESOURCES;
}
}
else
pdx->portbase = (PUCHAR) portbase.QuadPart;

NTSTATUS status = IoConnectInterrupt(&pdx->InterruptObject, (PKSERVICE_ROUTINE) OnInterrupt,(PVOID) pdx, NULL, vector, irql, irql, LevelSensitive, TRUE, affinity, FALSE);
if (!NT_SUCCESS(status))
{
KdPrint((“IoConnectInterrupt failed - %X\n”, status));
if (pdx->portbase && pdx->mappedport)
MmUnmapIoSpace(pdx->portbase, pdx->nports);
pdx->portbase = NULL;
return status;
}

#define IMAGE_LENGTH (640*480)
PHYSICAL_ADDRESS maxAddress;
maxAddress.u.LowPart = 0xFFFFFFFF;
maxAddress.u.HighPart = 0;

pdx->MemForImage = MmAllocateContiguousMemory(IMAGE_LENGTH,maxAddress);

PHYSICAL_ADDRESS pycialAddressForImage = MmGetPhysicalAddress(pdx->MemForImage);

WRITE_REGISTER_BUFFER_UCHAR((PUCHAR)pdx->MemBar0+0x10000,
(PUCHAR)&pycialAddressForImage.u.LowPart,4);

return STATUS_SUCCESS;
}

#pragma PAGEDCODE
NTSTATUS HelloWDMDispatchRoutine(IN PDEVICE_OBJECT fdo, IN PIRP Irp)
{
PAGED_CODE();
KdPrint((“Enter HelloWDMDispatchRoutine\n”));
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0; // no bytes xfered
IoCompleteRequest( Irp, IO_NO_INCREMENT );
KdPrint((“Leave HelloWDMDispatchRoutine\n”));
return STATUS_SUCCESS;
}

wxhsdp@163.com wrote:

here is the code, it’s from an example, thanks!

I don’t see anywhere in here that you tell your device to start issuing
interrupts. You get the system ready to receive them, but where do you
tell the device to start generating them?

And you should be doing this in KMDF.

pdx->MemForImage = MmAllocateContiguousMemory(IMAGE_LENGTH,maxAddress);

PHYSICAL_ADDRESS pycialAddressForImage = MmGetPhysicalAddress(pdx->MemForImage);

WRITE_REGISTER_BUFFER_UCHAR((PUCHAR)pdx->MemBar0+0x10000,
(PUCHAR)&pycialAddressForImage.u.LowPart,4);

That should be WRITE_REGUSTER_ULONG, not … BUFFER_UCHAR. Also, the
word is spelled “physical”, not “pycial”.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

> I don’t see anywhere in here that you tell your device to start issuing
interrupts. You get the system ready to receive them, but where do you
tell the device to start generating them?

thank you very much for your concern!
my device is self-made, its code is in xilinx SDK. i write a self-defined reg and the device will assert interrupt by lowering IRQ pin A. Is that enough, or some more codes maybe needed?

i read the pci configuration space and the interrupt bit in status reg is one, does that means the device have already issued the interrupt?

wxhsdp@163.com wrote:

> I don’t see anywhere in here that you tell your device to start issuing interrupts. You get the system ready to receive them, but where do you tell the device to start generating them?
my device is self-made, its code is in xilinx SDK. i write a self-defined reg and the device will assert interrupt by lowering IRQ pin A. Is that enough, or some more codes maybe needed?

So, is this the Xilinx PCI core?

Your device needs to have a couple of things in order to implement an
interrupt reasonably. There needs to be a bit to enable and disable
interrupts. When that bit is not enabled, your board must not assert
the PCI interrupt pin, even if an interrupt condition occurs. Your
driver turns this on during startup, some time after you call
IoConnectInterrupt, and is turned off at shutdown time, before you
IoDisconnectInterrupt.

Then, you need to have a readable bit you can read that says “an
interrupt condition was raised”. When your board asserts the IRQ pin,
it also needs to assert this bit. That way, your ISR can read this bit
to see if your board really was the one that triggered the interrupt.

Then, you need to have a writable bit to say “the current interrupt
condition has been handled”. You will write this in your ISR or your
DPC after you have finished processing, and that allows the board to
interrupt again.

i read the pci configuration space and the interrupt bit in status reg is one, does that means the device have already issued the interrupt?

Yes. Is the Interrupt Disable bit clear in the command register?


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

> Yes. Is the Interrupt Disable bit clear in the command register?

ye, it’s clear by default

in WDM driver mode, it seems that the system will automatically set the pci configuration space for my pnp pci device. the command register is 0x6, and the status register is 0x230 by default. when the pci device issues the interrupt, the status register become 0x238. is there any problem?

i try to use WinDbg to see something internal.

before i start the device:
Dumping IDT:
37: 806e6864
3d: 806e7e2c
41: 806e7c88
50: 806e693c
73: 8a24ea54 ba473e54 (KINTERRUPT 8a24ea18)
ba473e54 (KINTERRUPT 8a1ecbb0)
83: 8a2f9044 ba473e54 (KINTERRUPT 8a2f9008)
92: 8a37f4c4 ba9289c0 (KINTERRUPT 8a37f488)
94: 8a201a54 ba473e54 (KINTERRUPT 8a201a18)
ba473e54 (KINTERRUPT 8a339bb0)
a4: 8a25fbec ba473e54 (KINTERRUPT 8a25fbb0)
b1: 8a37e5bc ba78431e (KINTERRUPT 8a37e580)
b2: 8a3844bc ba9289c0 (KINTERRUPT 8a384480)
b4: 8a384954 ba65e67e (KINTERRUPT 8a384918)
ba65e67e (KINTERRUPT 8a2e5bb0)
ba473e54 (KINTERRUPT 8a256bb0)
ba473e54 (KINTERRUPT 8a1f8bb0)
c1: 806e6ac0
d1: 806e5e54
e1: 806e7048
e3: 806e6dac
fd: 806e75a8
fe: 806e7748

after i start the device
Dumping IDT:
37: 806e6864
3d: 806e7e2c
41: 806e7c88
50: 806e693c
73: 8a24ea54 ba473e54 (KINTERRUPT 8a24ea18)
ba473e54 (KINTERRUPT 8a1ecbb0)
83: 8a2f9044 ba473e54 (KINTERRUPT 8a2f9008)
92: 8a37f4c4 ba9289c0 (KINTERRUPT 8a37f488)
94: 8a201a54 ba473e54 (KINTERRUPT 8a201a18)
ba473e54 (KINTERRUPT 8a339bb0)
a4: 8a25fbec ba473e54 (KINTERRUPT 8a25fbb0)
b1: 8a37e5bc ba78431e (KINTERRUPT 8a37e580)
b2: 8a3844bc ba9289c0 (KINTERRUPT 8a384480)
b4: 8a384954 ba65e67e (KINTERRUPT 8a384918)
ba65e67e (KINTERRUPT 8a2e5bb0)
ba473e54 (KINTERRUPT 8a256bb0)
ba473e54 (KINTERRUPT 8a1f8bb0)
bac74404 (KINTERRUPT 89ff1bb0)
c1: 806e6ac0
d1: 806e5e54
e1: 806e7048
e3: 806e6dac
fd: 806e75a8
fe: 806e7748

bac74404 (KINTERRUPT 89ff1bb0) under b4 appears after i start the device. i take a look at the memory 0xbac74404, compare it with the assembly code and find out it’s just my ISR routine. is there any problem there are five ISRs under b4? additionally i saw someone use !idt with the ISR routine name acompany with the address, how to do that?

lkd> !apic
Apic @ fffe0000 ID:1 (50014) LogDesc:02000000 DestFmt:ffffffff TPR 41
TimeCnt: 0fdad680clk SpurVec:1f FaultVec:e3 error:0
Ipi Cmd: 0100000000040041 Vec:41 FixedDel Dest=Self edg high Timer..: 00000000000300fd Vec:FD FixedDel Dest=Self edg high m
Linti0.: 000000000001001f Vec:1F FixedDel Dest=Self edg high m Linti1.: 00000000000184ff Vec:FF NMI Dest=Self lvl high m
TMR: 73, 94, A4, B1, B4
IRR:
ISR:
Does mask means Linti0 is masked and no interrupt can be issued to the CPU? actually i do not know the exact mean about the information showing above by !apic. can anyone tell me something or give me a detailed tutorial?

lkd> !ioapic
Error retrieving address of HalpMpInfoTable, i have search it on google, but there’s no useful info.

wxhsdp@163.com wrote:

in WDM driver mode, it seems that the system will automatically set the pci configuration space for my pnp pci device. the command register is 0x6, and the status register is 0x230 by default. when the pci device issues the interrupt, the status register become 0x238. is there any problem?

Do you have the PCI spec, or a book that explains it? This doesn’t have
anything to do with “WDM driver mode”. This is PCI mechanics. The
command register is written by the PCI bus controller (6 means your
memory space is enabled, and you are allowed to act as bus master), but
the status register is maintained by your device. When your device has
an interrupt, it sets bit 3 in its status register.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

wxhsdp@163.com wrote:

i try to use WinDbg to see something internal.

bac74404 (KINTERRUPT 89ff1bb0) under b4 appears after i start the device. i take a look at the memory 0xbac74404, compare it with the assembly code and find out it’s just my ISR routine. is there any problem there are five ISRs under b4?

That’s what “shared interrupts” are all about. That’s why it is so
important for you to be able to tell for certain whether it was your
device that issued the interrupt. Your ISR might get called any time
ANY of those 5 devices fire an interrupt. If it wasn’t you, you need to
return FALSE.

Does mask means Linti0 is masked and no interrupt can be issued to the CPU? actually i do not know the exact mean about the information showing above by !apic. can anyone tell me something or give me a detailed tutorial?

You’re chasing rainbows here. You’re trying to blame your interrupt
problem on something in the Windows kernel. This kernel has been
handling interrupts for more than 20 years. It knows how to do that, as
long as you follow the rules.

What does your OnInterrupt code look like? I don’t think you showed us
that.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

> What does your OnInterrupt code look like? I don’t think you showed us
that.

i do not do anything in it, just Kdprint “have interrupt” for now. i just want to see the interrupt served first.