Equivalent function local_irq_disable()(Linux)

I am currently porting Linux driver code in to windows. I have a question.
Did anyone know equivalent function local_irq_disable() in windows. This function is used to disable the interrupts on the local processor.

Bottom line you should not be doing this in Windows. Redesign the code to
avoid stuff like this.


Don Burn (MVP, Windows DDK)
Windows 2k/XP/2k3 Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr
Remove StopSpam to reply

wrote in message news:xxxxx@ntdev…
>I am currently porting Linux driver code in to windows. I have a question.
> Did anyone know equivalent function local_irq_disable() in windows. This
> function is used to disable the interrupts on the local processor.
>

This is common design in most embedded OS to disable the interrupt on the local or source while in the interrupt handler . This allows to stop the device from the interrupting. Here are some eaxamples.

in VxWorks
//------------------------------------------------------------------------------
// Interrupt handler
//
// Called at interrupt level when the Marvell PHY detects a link change, this
// routine wakes up the link detect task to perform link related stuff.
void
OvEtherLink::linkDetHdlr(int parm)
{
intDisable(IQ8134X_INT_XINT7);

FnetEvent *event = (FnetEvent *) parm;
event->signal();
}

intDisable is VxWorks function to disable particular interrupt on the local device. I have also seen examples in windows
This is windows function WDF sample for PciDrv. In example the interrupts are disable on the source
//
// We process the interrupt if it’s not disabled and it’s active
//
if (!NIC_INTERRUPT_DISABLED(FdoData) && NIC_INTERRUPT_ACTIVE(FdoData))
{
InterruptRecognized = TRUE;

//
// Disable the interrupt (will be re-enabled in NICEvtInterruptDpc
//
NICDisableInterrupt(FdoData);

//
// Acknowledge the interrupt(s) and get the interrupt status
//

NIC_ACK_INTERRUPT(FdoData, IntStatus);

WdfInterruptQueueDpcForIsr( Interrupt );

}

So my questionis how can you disable the interrupt on the local processor in windows. I hope you are more specific about instead of throwing statements like you should not be using this.

And Windows is specifically designed on the principle you do not do this.
The reason for IRQL’s was in part so that interrupts would not be disabled,
instead one device can interrupt an ISR of another. Trying to force this
concept into Windows will create a flawed driver.


Don Burn (MVP, Windows DDK)
Windows 2k/XP/2k3 Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr
Remove StopSpam to reply

wrote in message news:xxxxx@ntdev…
> This is common design in most embedded OS to disable the interrupt on the
> local or source while in the interrupt handler . This allows to stop the
> device from the interrupting. Here are some eaxamples.
>
> in VxWorks
> //------------------------------------------------------------------------------
> // Interrupt handler
> //
> // Called at interrupt level when the Marvell PHY detects a link change,
> this
> // routine wakes up the link detect task to perform link related stuff.
> void
> OvEtherLink::linkDetHdlr(int parm)
> {
> intDisable(IQ8134X_INT_XINT7);
>
> FnetEvent *event = (FnetEvent *) parm;
> event->signal();
> }
>
> intDisable is VxWorks function to disable particular interrupt on the
> local device. I have also seen examples in windows
> This is windows function WDF sample for PciDrv. In example the interrupts
> are disable on the source
> //
> // We process the interrupt if it’s not disabled and it’s active
> //
> if (!NIC_INTERRUPT_DISABLED(FdoData) && NIC_INTERRUPT_ACTIVE(FdoData))
> {
> InterruptRecognized = TRUE;
>
> //
> // Disable the interrupt (will be re-enabled in NICEvtInterruptDpc
> //
> NICDisableInterrupt(FdoData);
>
> //
> // Acknowledge the interrupt(s) and get the interrupt status
> //
>
> NIC_ACK_INTERRUPT(FdoData, IntStatus);
>
>
> WdfInterruptQueueDpcForIsr( Interrupt );
>
> }
>
> So my questionis how can you disable the interrupt on the local processor
> in windows. I hope you are more specific about instead of throwing
> statements like you should not be using this.
>
>

It looks like NICDisableInterrupt does not disable the cpu interrupt, it
disables the interrupt on the adapter.

Bill Wandel

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com]
On Behalf Of xxxxx@hotmail.com
Sent: Thursday, July 10, 2008 12:41 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Equivalent function local_irq_disable()(Linux)

This is common design in most embedded OS to disable the interrupt on the
local or source while in the interrupt handler . This allows to stop the
device from the interrupting. Here are some eaxamples.

in VxWorks
//--------------------------------------------------------------------------

// Interrupt handler
//
// Called at interrupt level when the Marvell PHY detects a link change,
this // routine wakes up the link detect task to perform link related stuff.
void
OvEtherLink::linkDetHdlr(int parm)
{
intDisable(IQ8134X_INT_XINT7);

FnetEvent *event = (FnetEvent *) parm;
event->signal();
}

intDisable is VxWorks function to disable particular interrupt on the local
device. I have also seen examples in windows This is windows function WDF
sample for PciDrv. In example the interrupts are disable on the source //
// We process the interrupt if it’s not disabled and it’s active
//
if (!NIC_INTERRUPT_DISABLED(FdoData) && NIC_INTERRUPT_ACTIVE(FdoData))
{
InterruptRecognized = TRUE;

//
// Disable the interrupt (will be re-enabled in NICEvtInterruptDpc
//
NICDisableInterrupt(FdoData);

//
// Acknowledge the interrupt(s) and get the interrupt status
//

NIC_ACK_INTERRUPT(FdoData, IntStatus);

WdfInterruptQueueDpcForIsr( Interrupt );

}

So my questionis how can you disable the interrupt on the local processor
in windows. I hope you are more specific about instead of throwing
statements like you should not be using this.


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

xxxxx@hotmail.com wrote:

This is common design in most embedded OS to disable the interrupt on the local or source while in the interrupt handler . This allows to stop the device from the interrupting. Here are some eaxamples.

So my questionis how can you disable the interrupt on the local processor in windows. I hope you are more specific about instead of throwing statements like you should not be using this.

In Windows, interrupts are always disabled while an interrupt handler is
executing. There’s no need to call an API to do that.

In my experience, virtually every operating system, including embedded
operating systems, do exactly the same thing. Otherwise, it’s very
difficult to stop some devices from interrupting.


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

Tim:

Here is example from WDF sample example for PciDrv. This is interrupt handler code

BOOLEAN
NICEvtInterruptIsr(
IN WDFINTERRUPT Interrupt,
IN ULONG MessageID
)
/*++
Routine Description:

Interrupt handler for the device.

Arguments:

Interupt - Address of the framework interrupt object
MessageID -

Return Value:

TRUE if our device is interrupting, FALSE otherwise.

–*/
{
BOOLEAN InterruptRecognized = FALSE;
PFDO_DATA FdoData = NULL;
USHORT IntStatus;

UNREFERENCED_PARAMETER( MessageID );

TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INTERRUPT, “–> NICEvtInterruptIsr\n”);

FdoData = FdoGetData(WdfInterruptGetDevice(Interrupt));

//
// We process the interrupt if it’s not disabled and it’s active
//
if (!NIC_INTERRUPT_DISABLED(FdoData) && NIC_INTERRUPT_ACTIVE(FdoData))
{
InterruptRecognized = TRUE;

//
// Disable the interrupt (will be re-enabled in NICEvtInterruptDpc
//
NICDisableInterrupt(FdoData);

//
// Acknowledge the interrupt(s) and get the interrupt status
//

NIC_ACK_INTERRUPT(FdoData, IntStatus);

WdfInterruptQueueDpcForIsr( Interrupt );

}

TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INTERRUPT, “<– NICEvtInterruptIsr\n”);

return InterruptRecognized;
}

Could then explain the need for NICDisableInterrupt() ?

xxxxx@hotmail.com wrote:

Tim:

Here is example from WDF sample example for PciDrv. This is interrupt handler code

BOOLEAN
NICEvtInterruptIsr(

// We process the interrupt if it’s not disabled and it’s active
//
if (!NIC_INTERRUPT_DISABLED(FdoData) && NIC_INTERRUPT_ACTIVE(FdoData))
{
InterruptRecognized = TRUE;

//
// Disable the interrupt (will be re-enabled in NICEvtInterruptDpc
//
NICDisableInterrupt(FdoData);

//
// Acknowledge the interrupt(s) and get the interrupt status
//

NIC_ACK_INTERRUPT(FdoData, IntStatus);

WdfInterruptQueueDpcForIsr( Interrupt );

}

Could then explain the need for NICDisableInterrupt() ?

Sure. That tells the DEVICE to stop interrupting. That’s not disabling
the processor’s interrupts. Processor interrupts are disabled
throughout this routine, as they are in virtually all operating systems.


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

NicDisableInterrupt disables the interrupt on the NIC, not on the CPU.


Don Burn (MVP, Windows DDK)
Windows 2k/XP/2k3 Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr
Remove StopSpam to reply

wrote in message news:xxxxx@ntdev…
> Tim:
>
> Here is example from WDF sample example for PciDrv. This is interrupt
> handler code
>
> BOOLEAN
> NICEvtInterruptIsr(
> IN WDFINTERRUPT Interrupt,
> IN ULONG MessageID
> )
> /++
> Routine Description:
>
> Interrupt handler for the device.
>
> Arguments:
>
> Interupt - Address of the framework interrupt object
> MessageID -
>
> Return Value:
>
> TRUE if our device is interrupting, FALSE otherwise.
>
> –
/
> {
> BOOLEAN InterruptRecognized = FALSE;
> PFDO_DATA FdoData = NULL;
> USHORT IntStatus;
>
> UNREFERENCED_PARAMETER( MessageID );
>
> TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INTERRUPT, “–>
> NICEvtInterruptIsr\n”);
>
> FdoData = FdoGetData(WdfInterruptGetDevice(Interrupt));
>
> //
> // We process the interrupt if it’s not disabled and it’s active
> //
> if (!NIC_INTERRUPT_DISABLED(FdoData) && NIC_INTERRUPT_ACTIVE(FdoData))
> {
> InterruptRecognized = TRUE;
>
> //
> // Disable the interrupt (will be re-enabled in NICEvtInterruptDpc
> //
> NICDisableInterrupt(FdoData);
>
> //
> // Acknowledge the interrupt(s) and get the interrupt status
> //
>
> NIC_ACK_INTERRUPT(FdoData, IntStatus);
>
> WdfInterruptQueueDpcForIsr( Interrupt );
>
> }
>
> TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INTERRUPT, “<–
> NICEvtInterruptIsr\n”);
>
> return InterruptRecognized;
> }
>
> Could then explain the need for NICDisableInterrupt() ?
>

> Did anyone know equivalent function local_irq_disable() in windows.

KeRaiseIrql() with IRQL==HIGH_LEVEL will disable all maskable interrupts on a given CPU. However, as Don alredy pointed out, this is not the right thing to do. More on it below

This is common design in most embedded OS to disable the interrupt on the local
or source while in the interrupt handler

On x86 if interrupt is vectored via interrupt, rather than trap gate, interrupts will be disabled when handler stub starts execution. However, one of the very first things it will do is re-enable them before invoking
your ISR. Certainly , the OS has to prevent a given IRQ from causing interrupts while ISR executes.
The way it does so is OS-specific. For example, Linux will just disable IRQ. It has to do so, because it
issues EOI (i.e. tells interrupt controller that interrupt has been handled) before invoking ISR, which will result in interrupt storm if interrupt is level-triggered. Windows will raise IRQL to the appropriate level, effectively masking off all interrupts of lower or equal priority. This step is not really needed if ISR services a single IRQ, because interrupt controller will hold all interrupts of lower or equal priority until it receives EIO anyway (Windows issues EOI only after interrupt has been handled). However, if the same ISR services multiple IRQs, raising IRQL becomes a step of vital importance - otherwise, ISR may well re-enter itself if another IRQ that a given ISR services raises interrupt and this interrupt is of higher priority. Therefore, in order to avoid this scenario, Windows will raise IRQL to the level that corresponds to
the highest priority among interrupts that a given ISR services.

In any case, all these steps are taken by the OS before it invokes your ISR - you don’t have to be bothered about it when writing your code…

Anton Bassov

> This is common design in most embedded OS to disable the interrupt on the

local or source while in the interrupt handler .

In Windows, this particular interrupt is disabled till you are in the ISR.


Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com