|
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". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // e32test\nkernsa\nirqx.cpp |
|
15 // |
|
16 // |
|
17 |
|
18 #include <nk_irq.h> |
|
19 |
|
20 #ifdef __X86__ |
|
21 #include <apic.h> |
|
22 #endif |
|
23 |
|
24 class NIrqXTest : public NIrqX |
|
25 { |
|
26 public: |
|
27 NIrqXTest(); |
|
28 void Kick(); |
|
29 void Set(TBool aLevel); |
|
30 public: |
|
31 static void DoEoi(NIrq* aIrq); |
|
32 static void DoEnable(NIrq* aIrq); |
|
33 static void DoDisable(NIrq* aIrq); |
|
34 static void DoSetCpu(NIrq* aIrq, TUint32 aMask); |
|
35 static void DoInit(NIrq* aIrq); |
|
36 static TBool DoPending(NIrq* aIrq); |
|
37 static void DoWait(NIrq* aIrq); |
|
38 public: |
|
39 TSpinLock iLock; |
|
40 NIrq* iIrq; |
|
41 TUint32 iCpuMask; |
|
42 TUint8 iEnabled; |
|
43 TUint8 iPending; |
|
44 TUint8 iLevel; |
|
45 }; |
|
46 |
|
47 NIrqXTest::NIrqXTest() |
|
48 { |
|
49 iIrq = 0; |
|
50 iCpuMask = 0x1; |
|
51 iEnabled = 0; |
|
52 iPending = 0; |
|
53 iLevel = 0; |
|
54 } |
|
55 |
|
56 void NIrqXTest::Set(TBool aLevel) |
|
57 { |
|
58 TBool active = FALSE; |
|
59 TInt irq = __SPIN_LOCK_IRQSAVE(iLock); |
|
60 TUint32 f = iIrq->iStaticFlags; |
|
61 if (f & NIrq::ELevel) |
|
62 { |
|
63 if (f & NIrq::EPolarity) |
|
64 { |
|
65 active = aLevel; |
|
66 } |
|
67 else |
|
68 { |
|
69 active = !aLevel; |
|
70 } |
|
71 } |
|
72 else |
|
73 { |
|
74 if (f & NIrq::EPolarity) |
|
75 { |
|
76 active = aLevel && !iLevel; |
|
77 } |
|
78 else |
|
79 { |
|
80 active = !aLevel && iLevel; |
|
81 } |
|
82 } |
|
83 iLevel = (TUint8)(aLevel ? 1 : 0); |
|
84 if (active && iEnabled) |
|
85 Kick(); |
|
86 __SPIN_UNLOCK_IRQRESTORE(iLock,irq); |
|
87 } |
|
88 |
|
89 #if defined (__X86__) |
|
90 __NAKED__ void NIrqXTest::Kick() |
|
91 { |
|
92 _asm mov al, 1 |
|
93 _asm lock xchg al, [ecx]NIrqXTest.iPending |
|
94 _asm cmp al, 0 |
|
95 _asm jne short kick0 |
|
96 _asm mov eax, [ecx]NIrqXTest.iCpuMask |
|
97 _asm shl eax, 24 |
|
98 _asm jz short kick0 // no CPUs, so nothing to do |
|
99 _asm mov ds:[X86_LOCAL_APIC_BASE + X86_LOCAL_APIC_OFFSET_ICRH], eax |
|
100 _asm mov eax, [ecx]NIrqXTest.iIrq |
|
101 _asm mov eax, [eax]NIrq.iVector |
|
102 _asm or eax, 0x4800 |
|
103 _asm mov ds:[X86_LOCAL_APIC_BASE + X86_LOCAL_APIC_OFFSET_ICRL], eax |
|
104 _asm kick0: |
|
105 _asm ret |
|
106 } |
|
107 #endif |
|
108 |
|
109 void NIrqXTest::DoEoi(NIrq* aIrq) |
|
110 { |
|
111 NIrqXTest* pX = (NIrqXTest*)iX; |
|
112 TInt irq = __SPIN_LOCK_IRQSAVE(pX->iLock); |
|
113 if (pX->iPending) |
|
114 { |
|
115 pX->iPending = 0; |
|
116 TUint32 f = aIrq->iStaticFlags; |
|
117 if (f & NIrq::ELevel) |
|
118 { |
|
119 TUint active_level = (f & NIrq::EPolarity) ? 1 : 0; |
|
120 if (pX->iLevel==active_level && pX->iEnabled) |
|
121 pX->Kick(); |
|
122 } |
|
123 } |
|
124 __SPIN_UNLOCK_IRQRESTORE(pX->iLock,irq); |
|
125 } |
|
126 |
|
127 void NIrqXTest::DoEnable(NIrq* aIrq) |
|
128 { |
|
129 } |
|
130 |
|
131 void NIrqXTest::DoDisable(NIrq* aIrq) |
|
132 { |
|
133 } |
|
134 |
|
135 void NIrqXTest::DoSetCpu(NIrq* aIrq, TUint32 aMask) |
|
136 { |
|
137 } |
|
138 |
|
139 void NIrqXTest::DoInit(NIrq* aIrq) |
|
140 { |
|
141 iIrq = aIrq; |
|
142 } |
|
143 |
|
144 TBool NIrqXTest::DoPending(NIrq* aIrq) |
|
145 { |
|
146 } |
|
147 |
|
148 void NIrqXTest::DoWait(NIrq* aIrq) |
|
149 { |
|
150 } |
|
151 |