First public contribution.
1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of the License "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // e32\nkernsmp\x86\ncirq.cia
28 #define OFFSET_NIrqHandler_iHState 8
30 __ASSERT_COMPILE(_FOFF(NIrqHandler, iHState) == OFFSET_NIrqHandler_iHState);
33 // Atomically increment run count provided ECount set or count <2.
34 // If originally zero, atomically set CPU field
35 // Wait for EWait to be clear
36 // Return state of iIState immediately before increment
38 __NAKED__ TUint32 NIrq::EnterIsr()
45 asm("shr bl, 3 "); // BL = CPU number
46 asm("mov eax, [ecx+%0]" : : "i" _FOFF(NIrq,iIState));
47 asm("enterisr_loop: ");
49 asm("cmp edx, 0x10000 "); // compare run count to 1
50 asm("jae short enterisr_not0 "); // skip if >=1
51 asm("mov dh, bl "); // else update CPU
52 asm("enterisr_not0: ");
53 asm("add edx, 0x10000 "); // increment run count
54 asm("cmp edx, 0x20000 "); // compare to 2
55 asm("jb short enterisr_lt2 ");
56 asm("test dl, 6 "); // ECount|ERaw
57 asm("jz short enterisr_wait "); // if !ECount && !ERaw limit count to 2
58 asm("enterisr_lt2: ");
59 asm("lock cmpxchg [ecx+%0], edx" : : "i" _FOFF(NIrq,iIState));
60 asm("jne short enterisr_loop ");
62 asm("enterisr_wait: ");
63 asm("mov edx, 1 "); // EWait
64 asm("enterisr_loop1: ");
65 asm("test edx, [ecx+%0]" : : "i" _FOFF(NIrq,iIState));
66 asm("jnz short enterisr_loop2 "); // loop while EWait set
68 asm("lock add dword ptr [esp], 0 ");
71 asm("enterisr_loop2: ");
73 asm("jmp short enterisr_loop ");
77 // Atomically decrement run count
78 // Return TRUE if run count nonzero after decrement
80 __NAKED__ TBool NIrq::IsrDone()
83 asm("mov eax, 0xffff0000 "); // -1<<run count shift
84 asm("lock xadd [ecx+%0], eax" : : "i" _FOFF(NIrq,iIState));
86 asm("dec eax "); // eax=new run count = TRUE if nonzero
91 // Wait (allowing interrupts and preemption) until run count = 0 and EWait clear
92 // Then atomically set EWait and return with interrupts disabled
94 __NAKED__ void NIrq::Wait()
99 asm("mov eax, [ecx+%0]" : : "i" _FOFF(NIrq,iIState));
101 asm("mov edx, eax ");
102 asm("test edx, 0xffff0001 "); // test run count and EWait
103 asm("jnz short wait_loop2 "); // if not both zero, must wait
104 asm("inc edx "); // else try to set EWait
105 asm("lock cmpxchg [ecx+%0], edx" : : "i" _FOFF(NIrq,iIState));
106 asm("jne short wait_loop1 "); // someone beat us to it
107 THISCALL_EPILOG0() // success - return with interrupts disabled
109 // spin, allowing interrupts, while we wait for run count and EWait both zero
113 asm("jmp short wait_loop ");
117 // Atomically clear EWait and reenable interrupts
119 __NAKED__ void NIrq::Done()
122 asm("lock and dword ptr [ecx+%0], 0xfffffffe" : : "i" _FOFF(NIrq,iIState));
130 // atomic { if !EUnbind && !ENotReady clear EDisable }
131 // Return the initial value of iHState
133 __NAKED__ TUint32 NIrqHandler::DoSetEnabled()
136 asm("mov eax, [ecx+%0]" : : "i" _FOFF(NIrqHandler,iHState));
138 asm("mov edx, eax ");
139 asm("test dh, 0x0A "); // EUnbind|ENotReady
140 asm("jnz short dse_end "); // if either set, finished
141 asm("and dh, 0xFA "); // else try to clear EDisable and EBind
143 asm("lock cmpxchg [ecx+%0], edx" : : "i" _FOFF(NIrqHandler,iHState));
144 asm("jne short dse_loop "); // someone beat us to it
145 THISCALL_EPILOG0() // success - return original iHState
149 // Atomically increment run count by aCount if ECount set or run count initially zero.
150 // If !EDisable and !EUnbind set EActive
151 // Return initial iHState
153 __NAKED__ TUint32 NIrqHandler::DoActivate(TInt aCount)
156 asm("mov eax, [ecx+%0]" : : "i" _FOFF(NIrqHandler,iHState));
158 asm("mov edx, eax ");
159 asm("cmp edx, 0x10000 ");
160 asm("jb short da_zero "); // skip if run count initially zero
161 asm("test dh, 0x10 "); // else check ECount
162 asm("jz short da_end "); // if clear, don't increment
164 asm("mov edx, [esp+4] "); // edx = aCount
166 asm("add edx, eax "); // increment run count
168 asm("test dh, 0x03 "); // EUnbind|EDisable
169 asm("jnz short da_1 "); // skip if EUnbind or EDisable set
170 asm("or dh, 0x20 "); // set EActive
172 asm("lock cmpxchg [ecx+%0], edx" : : "i" _FOFF(NIrqHandler,iHState));
173 asm("jne short da_loop "); // someone beat us to it
174 THISCALL_EPILOG1() // success - return original iHState
178 // Decrement run count
179 // Return initial iHState
181 __NAKED__ TUint32 NIrqHandler::EventBegin()
184 asm("mov eax, 0xffff0000 "); // -1<<run count shift
185 asm("lock xadd [ecx+%0], eax" : : "i" _FOFF(NIrqHandler,iHState));
190 // If count is zero or EDisable or EUnbind
191 // are set, clear EActive.
192 // Return initial iHState, except for new EActive bit
194 __NAKED__ TUint32 NIrqHandler::EventDone()
197 asm("mov eax, [ecx+%0]" : : "i" _FOFF(NIrqHandler,iHState));
199 asm("mov edx, eax ");
200 asm("cmp edx, 0x10000 ");
201 asm("jb short ed_rc_0 "); // skip if run count now zero
202 asm("test dh, 0x03 "); // test EUnbind and EDisable
203 asm("jz short ed_1 "); // skip if neither set
205 asm("and dh, 0xDF "); // clear EActive
207 asm("lock cmpxchg [ecx+%0], edx" : : "i" _FOFF(NIrqHandler,iHState));
208 asm("jne short ed_loop "); // someone beat us to it
209 asm("or dh, 0xDF "); // set all except EActive
210 asm("and ah, dh "); // clear EActive in return value if we cleared it
211 THISCALL_EPILOG0() // success - return original iHState with new EActive