|
1 /* |
|
2 * Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of the License "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 /** |
|
20 @file |
|
21 @internalComponent |
|
22 @released |
|
23 */ |
|
24 #include <kernel/kern_priv.h> |
|
25 #include <cryptodriver.h> |
|
26 #ifdef __MARM__ |
|
27 #include <omap_hrp/assp/shared/omap_reg.h> |
|
28 #include <omap_hrp/assp/shared/omap_interrupt.h> |
|
29 #endif |
|
30 //#include "cryptoh4.h" |
|
31 #include "cryptoldd.h" |
|
32 #include "cryptoh4rng.h" |
|
33 |
|
34 inline void CryptoH4JobRandom::EnableIsr() |
|
35 { |
|
36 TRACE_FUNCTION("EnableIsr"); |
|
37 // Kern::Printf("EI"); |
|
38 SetRunning(ETrue); |
|
39 #ifdef __MARM__ |
|
40 // Enable RNG interrupt. This interrupt will then queue the |
|
41 // "random number ready" DFC |
|
42 TInt32 tmp = TOmap::Register32(KHwBaseRngReg + KHoRng_Mask); |
|
43 tmp |= 4; |
|
44 TOmap::SetRegister32(KHwBaseRngReg + KHoRng_Mask, tmp); |
|
45 #else |
|
46 // Not on real h/w so just queue the DFC... |
|
47 // Queue the "random number ready" DFC |
|
48 iRandomDfc.Enque(); // Queue from task level |
|
49 #endif |
|
50 } |
|
51 |
|
52 inline void CryptoH4JobRandom::DisableIsr() |
|
53 { |
|
54 TRACE_FUNCTION("DisableIsr"); |
|
55 // Kern::Printf("DI"); |
|
56 #ifdef __MARM__ |
|
57 TInt32 tmp = TOmap::Register32(KHwBaseRngReg + KHoRng_Mask); |
|
58 tmp &= ~4; |
|
59 TOmap::SetRegister32(KHwBaseRngReg + KHoRng_Mask, tmp); |
|
60 #endif |
|
61 } |
|
62 |
|
63 |
|
64 |
|
65 CryptoH4JobRandom::CryptoH4JobRandom(DLddChanRandom &aLddChanRandom) |
|
66 : iLddChanRandom(aLddChanRandom), |
|
67 iJobSizeInBytes(0), |
|
68 iSwReadByteOffset(0), |
|
69 iHw32Index(0), |
|
70 iIsrHooked(EFalse), |
|
71 iRandomDfc(RandomDfc, this, 1) // DFC is priority '1' |
|
72 { |
|
73 TRACE_FUNCTION("CryptoH4JobRandom"); |
|
74 // Kern::Printf("CryptoH4JobRandom::CryptoH4JobRandom %x", this); |
|
75 } |
|
76 |
|
77 CryptoH4JobRandom::~CryptoH4JobRandom() |
|
78 { |
|
79 TRACE_FUNCTION("~CryptoH4JobRandom"); |
|
80 // Kern::Printf("CryptoH4JobRandom::~CryptoH4JobRandom %x", this); |
|
81 UnHookIsr(); |
|
82 } |
|
83 |
|
84 |
|
85 void CryptoH4JobRandom::SetDfcQ(TDfcQue *aDfcQue) |
|
86 { |
|
87 TRACE_FUNCTION("SetDfcQ"); |
|
88 iRandomDfc.SetDfcQ(aDfcQue); |
|
89 } |
|
90 |
|
91 void CryptoH4JobRandom::SetDetails(DCryptoJobScheduler *aJobScheduler, |
|
92 MCryptoJobCallbacks *aCallbacks, |
|
93 TUint32 aNumOfBytes) |
|
94 { |
|
95 TRACE_FUNCTION("SetDetails"); |
|
96 // Kern::Printf("CryptoH4JobRandom::SetDetails"); |
|
97 iJobScheduler = aJobScheduler; |
|
98 iCallbacks = aCallbacks; |
|
99 iJobSizeInBytes = aNumOfBytes; |
|
100 } |
|
101 |
|
102 void CryptoH4JobRandom::GetToPddBuffer(TUint8 * &aBuf, TUint32 &aBufLen, TBool &aMore) |
|
103 { |
|
104 TRACE_FUNCTION("GetToPddBuffer"); |
|
105 aBuf = 0; |
|
106 aBufLen = 0; |
|
107 aMore = EFalse; |
|
108 } |
|
109 |
|
110 void CryptoH4JobRandom::BytesWrittenToPdd(TUint32) |
|
111 { |
|
112 TRACE_FUNCTION("BytesWrittenToPdd"); |
|
113 } |
|
114 |
|
115 void CryptoH4JobRandom::GetFromPddBuffer(TUint8 * &aBuf, TUint32 &aBufLen, TBool &aMore) |
|
116 { |
|
117 TRACE_FUNCTION("GetFromPddBuffer"); |
|
118 |
|
119 TInt hw8Index = iHw32Index * 4; |
|
120 TUint8 *p = (TUint8 *) iRandomBuffer; |
|
121 aBuf = &p[iSwReadByteOffset]; |
|
122 |
|
123 TInt len = hw8Index - iSwReadByteOffset; |
|
124 if(len >= 0) |
|
125 { |
|
126 aBufLen = len; |
|
127 aMore = EFalse; |
|
128 } |
|
129 else |
|
130 { |
|
131 // Wrap round condition, but can only return contiguous bytes |
|
132 aBufLen = sizeof(iRandomBuffer) - iSwReadByteOffset; |
|
133 aMore = ETrue; |
|
134 return; |
|
135 } |
|
136 } |
|
137 |
|
138 void CryptoH4JobRandom::BytesReadFromPdd(TUint32 aBytes) |
|
139 { |
|
140 TRACE_FUNCTION("BytesReadFromPdd"); |
|
141 iSwReadByteOffset += aBytes; |
|
142 if(iSwReadByteOffset >= sizeof(iRandomBuffer)) |
|
143 { |
|
144 iSwReadByteOffset -= sizeof(iRandomBuffer); |
|
145 } |
|
146 iJobSizeInBytes -= aBytes; |
|
147 } |
|
148 |
|
149 |
|
150 |
|
151 void CryptoH4JobRandom::DoSlice(TBool aFirstSlice) |
|
152 { |
|
153 TRACE_FUNCTION("DoSlice"); |
|
154 // Kern::Printf("DoSlice(%d)", aFirstSlice); |
|
155 if(aFirstSlice) |
|
156 { |
|
157 HookIsr(); |
|
158 } |
|
159 |
|
160 // Enable RNG interrupt. The interrupt will then queue the |
|
161 // "random number ready" DFC when the h/w is ready. |
|
162 // (when not on h/w, this immediately queues a DFC) |
|
163 EnableIsr(); |
|
164 } |
|
165 |
|
166 TBool CryptoH4JobRandom::DoSaveState() |
|
167 { |
|
168 TRACE_FUNCTION("DoSaveState"); |
|
169 UnHookIsr(); |
|
170 return ETrue; // We want DoRestoreState to be called |
|
171 } |
|
172 |
|
173 void CryptoH4JobRandom::DoRestoreState() |
|
174 { |
|
175 TRACE_FUNCTION("DoRestoreState"); |
|
176 HookIsr(); |
|
177 } |
|
178 |
|
179 void CryptoH4JobRandom::DoReleaseHw() |
|
180 { |
|
181 TRACE_FUNCTION("DoReleaseHw"); |
|
182 // Disable RNG interrupt |
|
183 DisableIsr(); |
|
184 |
|
185 // Disable/unhook ISR |
|
186 UnHookIsr(); |
|
187 |
|
188 // Cancel DFC |
|
189 iRandomDfc.Cancel(); |
|
190 |
|
191 } |
|
192 |
|
193 TInt CryptoH4JobRandom::BytesAvailable() const |
|
194 { |
|
195 TRACE_FUNCTION("BytesAvailable"); |
|
196 TInt hw8Index = iHw32Index * 4; |
|
197 TInt available = hw8Index - iSwReadByteOffset; |
|
198 if(available < 0) |
|
199 { |
|
200 available += sizeof(iRandomBuffer); |
|
201 } |
|
202 return available; |
|
203 } |
|
204 |
|
205 void CryptoH4JobRandom::RegionsAvailable(TUint8 * &aPtr1, TInt &aLen1, |
|
206 TUint8 * &aPtr2, TInt &aLen2) const |
|
207 { |
|
208 TRACE_FUNCTION("RegionsAvailable"); |
|
209 TInt hw8Index = iHw32Index * 4; |
|
210 TUint8 *p = (TUint8 *) iRandomBuffer; |
|
211 aPtr1 = &p[iSwReadByteOffset]; |
|
212 |
|
213 TInt len = hw8Index - iSwReadByteOffset; |
|
214 if(len < 0) |
|
215 { |
|
216 // Available data crosses buffer end so return two regions |
|
217 aLen1 = sizeof(iRandomBuffer) - iSwReadByteOffset; |
|
218 aPtr2 = &p[0]; |
|
219 aLen2 = hw8Index; |
|
220 } |
|
221 else |
|
222 { |
|
223 // Available buffer is contiguous |
|
224 aLen1 = len; |
|
225 aPtr2 = 0; |
|
226 aLen2 = 0; |
|
227 } |
|
228 } |
|
229 |
|
230 |
|
231 |
|
232 void CryptoH4JobRandom::HookIsr() |
|
233 { |
|
234 TRACE_FUNCTION("HookIsr"); |
|
235 // Kern::Printf("CryptoH4JobRandom::HookIsr iIsrHooked=%d this=%x", iIsrHooked, this); |
|
236 #ifdef __MARM__ |
|
237 if(!iIsrHooked) |
|
238 { |
|
239 TInt r = Interrupt::Bind(EIrqRng, Isr, this); |
|
240 if(r != KErrNone) Kern::Fault("CryptoH4JobRandom::HookIsr Bind failed", r); |
|
241 r = Interrupt::Enable(EIrqRng); |
|
242 if(r != KErrNone) Kern::Fault("CryptoH4JobRandom::HookIsr Enable failed", r); |
|
243 iIsrHooked = ETrue; |
|
244 } |
|
245 #endif |
|
246 } |
|
247 |
|
248 void CryptoH4JobRandom::UnHookIsr() |
|
249 { |
|
250 TRACE_FUNCTION("UnHookIsr"); |
|
251 // Kern::Printf("CryptoH4JobRandom::UnHookIsr iIsrHooked=%d this=%x", iIsrHooked, this); |
|
252 #ifdef __MARM__ |
|
253 if(iIsrHooked) |
|
254 { |
|
255 Interrupt::Disable(EIrqRng); |
|
256 Interrupt::Unbind(EIrqRng); |
|
257 iIsrHooked = EFalse; |
|
258 } |
|
259 #endif |
|
260 } |
|
261 |
|
262 |
|
263 |
|
264 #ifdef __MARM__ |
|
265 void CryptoH4JobRandom::Isr(TAny *aPtr) |
|
266 { |
|
267 TRACE_FUNCTION("Isr"); |
|
268 CryptoH4JobRandom *p = static_cast<CryptoH4JobRandom *>(aPtr); |
|
269 // Disable RNG interrupt so DFC can run. |
|
270 p->DisableIsr(); |
|
271 // Queue DFC to read the RNG |
|
272 p->iRandomDfc.Add(); |
|
273 } |
|
274 #endif |
|
275 |
|
276 /** |
|
277 Called when the current h/w opperation is complete |
|
278 */ |
|
279 void CryptoH4JobRandom::RandomDfc(TAny* aPtr) |
|
280 { |
|
281 ((CryptoH4JobRandom*)aPtr)->DoRandomDfc(); |
|
282 } |
|
283 |
|
284 void CryptoH4JobRandom::DoRandomDfc() |
|
285 { |
|
286 TRACE_FUNCTION("DoRandomDfc"); |
|
287 // Set state to not using hw, if we continue using the h/w we will |
|
288 // call EnableIsr which will change the state back to ERunning. |
|
289 SetRunning(EFalse); |
|
290 // Kern::Printf("DoRandomDfc"); |
|
291 #ifdef __MARM__ |
|
292 // Read h/w |
|
293 iRandomBuffer[iHw32Index] = TOmap::Register32(KHwBaseRngReg + KHoRng_Out); |
|
294 #else |
|
295 static TUint32 n = 0; |
|
296 iRandomBuffer[iHw32Index]= n++; |
|
297 #endif |
|
298 |
|
299 ++iHw32Index; |
|
300 if(iHw32Index >= sizeof(iRandomBuffer)/sizeof(iRandomBuffer[0])) |
|
301 { |
|
302 iHw32Index = 0; |
|
303 } |
|
304 |
|
305 TInt outputAvailable = BytesAvailable(); |
|
306 TInt space = sizeof(iRandomBuffer) - outputAvailable - 4; |
|
307 if((outputAvailable >= iJobSizeInBytes) || (space <= 0)) |
|
308 { |
|
309 // Either have enough data to finish job, or out of buffer |
|
310 // space to read more. We pass available data to the LDD, and |
|
311 // declare the slice/job done and return. |
|
312 |
|
313 // |
|
314 // Pass available data to LDD |
|
315 // |
|
316 // LDD will call GetFromPddBuffer/BytesReadFromPdd to read the data. |
|
317 iLddChanRandom.DataAvailable(); |
|
318 } |
|
319 |
|
320 // Are we done yet? |
|
321 if(iJobSizeInBytes <= 0) |
|
322 { |
|
323 // Tell the scheduler that this slice is done |
|
324 iJobScheduler->JobComplete(this, KErrNone); |
|
325 return; |
|
326 } |
|
327 |
|
328 // Re-calculate output available and space |
|
329 outputAvailable = BytesAvailable(); |
|
330 space = sizeof(iRandomBuffer) - outputAvailable - 4; |
|
331 |
|
332 if((space != 0) && (iJobSizeInBytes-outputAvailable > 0)) |
|
333 { |
|
334 // We have some space and we need more data |
|
335 |
|
336 // Enable RNG interrupt. The interrupt will then queue the |
|
337 // "random number ready" DFC when the h/w is ready. |
|
338 // (when not on h/w, this immediately queues a DFC) |
|
339 EnableIsr(); |
|
340 } |
|
341 else |
|
342 { |
|
343 // Job stalled - either out of space or already have enough |
|
344 // data but LDD has not take it |
|
345 Stalled(); |
|
346 } |
|
347 |
|
348 return; |
|
349 } |
|
350 |
|
351 |
|
352 |
|
353 |
|
354 // End of file |