|
1 // Copyright (c) 1994-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 // template\template_variant\specific\variant.cpp |
|
15 // |
|
16 // |
|
17 |
|
18 #include "variant.h" |
|
19 #include "mconf.h" |
|
20 #include <videodriver.h> |
|
21 #include <drivers/xyin.h> |
|
22 #include "template_power.h" |
|
23 |
|
24 //These constants define Custom Restart Reasons in SuperPage::iHwStartupReason |
|
25 const TUint KHtCustomRestartMax = 0xff; |
|
26 const TUint KHtCustomRestartShift = 8; |
|
27 const TUint KHtCustomRestartMask = KHtCustomRestartMax << KHtCustomRestartShift; |
|
28 |
|
29 const TUint KHtRestartStartupModesMax = 0xf; // Variable, platform dependant |
|
30 const TUint KHtRestartStartupModesShift = 16; // Variable, platform dependant |
|
31 const TUint KHtRestartStartupModesMask = KHtRestartStartupModesMax << KHtRestartStartupModesShift; |
|
32 |
|
33 void TemplateVariantFault(TInt aLine) |
|
34 { |
|
35 Kern::Fault("TemplateVariant",aLine); |
|
36 } |
|
37 |
|
38 #define V_FAULT() TemplateVariantFault(__LINE__) |
|
39 |
|
40 // Debug output |
|
41 #define XON 17 |
|
42 #define XOFF 19 |
|
43 #define DEBUG_XON_XOFF 0 // Non-zero if we want XON-XOFF handshaking |
|
44 |
|
45 GLDEF_D Template TheVariant; |
|
46 TUint32 Variant::iBaseAddress=0; |
|
47 |
|
48 TUint32 Template::HandlerData[3]; |
|
49 SInterruptHandler Template::Handlers[ENumXInts]; |
|
50 |
|
51 extern void XIntDispatch(TAny*); |
|
52 |
|
53 EXPORT_C Asic* VariantInitialise() |
|
54 { |
|
55 return &TheVariant; |
|
56 } |
|
57 |
|
58 Template::Template() |
|
59 { |
|
60 iDebugInitialised=EFalse; |
|
61 } |
|
62 |
|
63 // |
|
64 // TO DO: (optional) |
|
65 // |
|
66 // Specify the RAM zone configuration. |
|
67 // |
|
68 // The lowest addressed zone must have the highest preference as the bootstrap |
|
69 // will always allocate from the lowest address up. Once the kernel has initialised |
|
70 // then the zone preferences will decide from which RAM zone memory is allocated. |
|
71 // |
|
72 // const TUint KVariantRamZoneCount = ?; |
|
73 // static const SRamZone KRamZoneConfig[KVariantRamZoneCount+1] = |
|
74 // iBase iSize iID iPref iFlags |
|
75 // { |
|
76 // __SRAM_ZONE(0x????????, 0x???????, ?, ?, ?), |
|
77 // ... |
|
78 // __SRAM_ZONE(0x????????, 0x???????, ?, ?, ?), |
|
79 // __SRAM_ZONE_END, // end of zone list |
|
80 // }; |
|
81 // |
|
82 |
|
83 TInt Template::RamZoneCallback(TRamZoneOp aOp, TAny* aId, const TAny* aMasks) |
|
84 { |
|
85 // |
|
86 // TO DO: (optional) |
|
87 // |
|
88 // Handle RAM zone operations requested by the kernel. |
|
89 // |
|
90 return TheVariant.DoRamZoneCallback(aOp, (TUint)aId, (const TUint*)aMasks); |
|
91 } |
|
92 |
|
93 |
|
94 TInt Template::DoRamZoneCallback(TRamZoneOp aOp, TUint aId, const TUint* aMasks) |
|
95 { |
|
96 // |
|
97 // TO DO: (optional) |
|
98 // |
|
99 // Handle RAM zone operations requested by the kernel. |
|
100 // |
|
101 // Three types of operation need to be supported: |
|
102 // ERamZoneOp_Init: Update power state of the RAM zones after the |
|
103 // kernel has initialised. |
|
104 // ERamZoneOp_PowerUp: A RAM zone changing from used to empty. |
|
105 // ERamZoneOp_PowerDown: A RAM zone changing from empty to used. |
|
106 // |
|
107 |
|
108 switch (aOp) |
|
109 { |
|
110 case ERamZoneOp_Init: |
|
111 break; |
|
112 case ERamZoneOp_PowerUp: |
|
113 break; |
|
114 case ERamZoneOp_PowerDown: |
|
115 break; |
|
116 default: |
|
117 return KErrNotSupported; |
|
118 } |
|
119 return KErrNone; |
|
120 } |
|
121 |
|
122 |
|
123 void Template::Init1() |
|
124 { |
|
125 __KTRACE_OPT(KBOOT,Kern::Printf("Template::Init1()")); |
|
126 |
|
127 // |
|
128 // TO DO: (mandatory) |
|
129 // |
|
130 // Configure Memory controller and Memrory Bus parameters (in addition to what was done in the Bootstrap) |
|
131 // |
|
132 __KTRACE_OPT(KBOOT,Kern::Printf("Memory Configuration done")); |
|
133 |
|
134 // |
|
135 // TO DO: (optional) |
|
136 // |
|
137 // Inform the kernel of the RAM zone configuration via Epoc::SetRamZoneConfig(). |
|
138 // For devices that wish to reduce power consumption of the RAM IC(s) the callback functions |
|
139 // RamZoneCallback() and DoRamZoneCallback() will need to be implemented and passed |
|
140 // to Epoc::SetRamZoneConfig() as the parameter aCallback. |
|
141 // The kernel will assume that all RAM ICs are fully intialised and ready for use from boot. |
|
142 // |
|
143 |
|
144 // |
|
145 // TO DO: (optional) |
|
146 // |
|
147 // Initialise other critical hardware functions such as I/O interfaces, etc, not done by Bootstrap |
|
148 // |
|
149 // if CPU is Sleep-capable, and requires some preparation to be put in that state (code provided in Bootstrap), |
|
150 // the address of the idle code is writen at this location by the Bootstrap |
|
151 // e.g. |
|
152 // iIdleFunction=*(TLinAddr*)((TUint8*)&Kern::SuperPage()+0x1000); |
|
153 // |
|
154 TemplateAssp::Init1(); |
|
155 } |
|
156 |
|
157 void Template::Init3() |
|
158 { |
|
159 __KTRACE_OPT(KBOOT,Kern::Printf("Template::Init3()")); |
|
160 |
|
161 TemplateAssp::Init3(); |
|
162 |
|
163 Variant::Init3(); |
|
164 // |
|
165 // TO DO: (optional) |
|
166 // |
|
167 // Initialise other accessor classes, if required |
|
168 // |
|
169 |
|
170 InitInterrupts(); |
|
171 } |
|
172 |
|
173 void Variant::Init3() |
|
174 // |
|
175 // Phase 3 initialisation |
|
176 // |
|
177 { |
|
178 __KTRACE_OPT(KHARDWARE, Kern::Printf(">Variant::Init3")); |
|
179 |
|
180 // |
|
181 // TO DO: (optional) |
|
182 // |
|
183 // Initialise any Variant class data members here, map in Variant and external hardware addresses |
|
184 // |
|
185 DPlatChunkHw* pC=NULL; |
|
186 TInt r=DPlatChunkHw::New(pC,KHwVariantPhysBase,0x2000,EMapAttrSupRw|EMapAttrFullyBlocking); |
|
187 __ASSERT_ALWAYS(r==KErrNone,V_FAULT()); |
|
188 iBaseAddress=pC->LinearAddress(); |
|
189 } |
|
190 |
|
191 EXPORT_C TUint Variant::BaseLinAddress() |
|
192 { |
|
193 return((TUint)iBaseAddress); |
|
194 } |
|
195 |
|
196 EXPORT_C void Variant::MarkDebugPortOff() |
|
197 { |
|
198 TheVariant.iDebugInitialised=EFalse; |
|
199 } |
|
200 |
|
201 EXPORT_C void Variant::UartInit() |
|
202 { |
|
203 NKern::Lock(); |
|
204 if (!TheVariant.iDebugInitialised) |
|
205 { |
|
206 // |
|
207 // TO DO: (mandatory) |
|
208 // |
|
209 // Reset and initialise the UART used to output debug strings |
|
210 // |
|
211 TheVariant.iDebugInitialised=ETrue; |
|
212 } |
|
213 NKern::Unlock(); |
|
214 } |
|
215 |
|
216 void Template::DebugInit() |
|
217 { |
|
218 // |
|
219 // TO DO: (mandatory) |
|
220 // |
|
221 // Initialise the UART used for outputting Debug Strings (no Interrupts), as in the following EXAMPLE ONLY: |
|
222 // |
|
223 Variant::UartInit(); |
|
224 TTemplate::BootWaitMilliSeconds(10); // wait loop to ensure that the port is fully initialised and output buffer empty |
|
225 } |
|
226 |
|
227 void Template::DebugOutput(TUint aLetter) |
|
228 // |
|
229 // Output a character to the debug port |
|
230 // |
|
231 { |
|
232 if (!iDebugInitialised) |
|
233 { |
|
234 DebugInit(); |
|
235 } |
|
236 // |
|
237 // TO DO: (mandatory) |
|
238 // |
|
239 // Write the character aLetter to the UART output register and wait until sent (do NOT use interrupts!) |
|
240 // |
|
241 } |
|
242 |
|
243 void Template::Idle() |
|
244 // |
|
245 // The NULL thread idle loop |
|
246 // |
|
247 { |
|
248 // Idle the CPU, suppressing the system tick if possible |
|
249 |
|
250 // |
|
251 // TO DO: (optional) |
|
252 // |
|
253 // Idle Tick supression: |
|
254 // 1- obtain the number of idle Ticks before the next NTimer expiration (NTimerQ::IdleTime()) |
|
255 // 2- if the number of Ticks is large enough (criteria to be defined) reset the Hardware Timer |
|
256 // to only interrupt again when the corresponding time has expired. |
|
257 // 2.1- the calculation of the new value to program the Hardware Timer with should take in |
|
258 // consideration the rounding value (NTimerQ::iRounding) |
|
259 // 3- call the low level Sleep function (e'g. Bootstrap: address in iIdleFunction) |
|
260 // 4- on coming back from Idle need to read the Hardware Timer and determine if woken up due to |
|
261 // timer expiration (system time for new match<=current system time<system time for new match-tick period) |
|
262 // or some other Interrupt. |
|
263 // 4.1- if timer expiration, adjust System Time by adding the number of Ticks suppressed to NTimerQ::iMsCount |
|
264 // 4.2- if other interrupt, calculate the number of Ticks skipped until woken up and adjust the System Time as |
|
265 // above |
|
266 // |
|
267 // Support for different Sleep Modes: |
|
268 // Often the Sleep mode a platform can go to depends on how many resources such as clocks/voltages can be |
|
269 // turned Off or lowered to a suitable level. If different Sleep modes are supported this code may need |
|
270 // to be able to find out what power resources are On or Off or used to what level. This could be achieved by |
|
271 // enquiring the Resource Manager (see \template_variant\inc\template_power.h). |
|
272 // Then a decision could be made to what Sleep level we go to. |
|
273 // |
|
274 // Example calls: |
|
275 // Obtain the number of Idle Ticks before the next NTimer expiration |
|
276 // TInt aTicksLeft = NTimerQ::IdleTime(); |
|
277 // ... |
|
278 // Find out the deepest Sleep mode available for current resource usage and sleeping time |
|
279 // TemplateResourceManager* aManager = TTemplatePowerController::ResourceManager(); |
|
280 // TemplateResourceManager::TSleepModes aMode = aManager -> MapSleepMode(aTicksLeft*MsTickPeriod()); |
|
281 // ... |
|
282 // Find out the state of some particular resources |
|
283 // TBool aResourceState = aManager -> GetResourceState(TemplateResourceManager::AsynchBinResourceUsedByZOnly); |
|
284 // TUint aResourceLevel = aManager -> GetResourceLevel(TemplateResourceManager::SynchMlResourceUsedByXOnly); |
|
285 // ... |
|
286 } |
|
287 |
|
288 TInt Template::VariantHal(TInt aFunction, TAny* a1, TAny* a2) |
|
289 { |
|
290 TInt r=KErrNone; |
|
291 switch(aFunction) |
|
292 { |
|
293 case EVariantHalVariantInfo: |
|
294 { |
|
295 TVariantInfoV01Buf infoBuf; |
|
296 TVariantInfoV01& info=infoBuf(); |
|
297 info.iRomVersion=Epoc::RomHeader().iVersion; |
|
298 |
|
299 // |
|
300 // TO DO: (mandatory) |
|
301 // |
|
302 // Fill in the TVariantInfoV01 info structure |
|
303 // info.iMachineUniqueId=; |
|
304 // info.iLedCapabilities=; |
|
305 // info.iProcessorClockInKHz=; |
|
306 // info.iSpeedFactor=; |
|
307 // |
|
308 Kern::InfoCopy(*(TDes8*)a1,infoBuf); |
|
309 break; |
|
310 } |
|
311 case EVariantHalDebugPortSet: |
|
312 { |
|
313 // |
|
314 // TO DO: (mandatory) |
|
315 // |
|
316 // Write the iDebugPort field of the SuperPage, as in the following EXAMPLE ONLY: |
|
317 // |
|
318 TUint32 thePort = (TUint32)a1; |
|
319 switch(thePort) |
|
320 { |
|
321 case 1: |
|
322 case 2: |
|
323 case 3: |
|
324 TheVariant.iDebugInitialised=EFalse; |
|
325 case (TUint32)KNullDebugPort: |
|
326 Kern::SuperPage().iDebugPort = thePort; |
|
327 break; |
|
328 default: |
|
329 r=KErrNotSupported; |
|
330 } |
|
331 break; |
|
332 } |
|
333 case EVariantHalDebugPortGet: |
|
334 { |
|
335 // |
|
336 // TO DO: (mandatory) |
|
337 // |
|
338 // Obtain the Linear address of the Uart used for outputting Debug strings as in the following EXAMPLE ONLY: |
|
339 // |
|
340 |
|
341 TUint32 thePort = TTemplate::DebugPortAddr(); |
|
342 kumemput32(a1, &thePort, sizeof(TUint32)); |
|
343 break; |
|
344 } |
|
345 case EVariantHalSwitches: |
|
346 { |
|
347 // |
|
348 // TO DO: (optional) |
|
349 // |
|
350 // Read the state of any switches, as in the following EXAMPLE ONLY: |
|
351 // |
|
352 TUint32 x = Variant::Switches(); |
|
353 kumemput32(a1, &x, sizeof(x)); |
|
354 break; |
|
355 } |
|
356 case EVariantHalLedMaskSet: |
|
357 { |
|
358 // |
|
359 // TO DO: (optional) |
|
360 // |
|
361 // Set the state of any on-board LEDs, e.g: |
|
362 // TUint32 aLedMask=(TUint32)a1; |
|
363 // Variant::ModifyLedState(~aLedMask,aLedMask); |
|
364 // |
|
365 break; |
|
366 } |
|
367 case EVariantHalLedMaskGet: |
|
368 { |
|
369 // |
|
370 // TO DO: (optional) |
|
371 // |
|
372 // Read the state of any on-board LEDs, e.g: |
|
373 // TUint32 x = Variant::LedState(); |
|
374 // kumemput32(a1, &x, sizeof(x)); |
|
375 // |
|
376 break; |
|
377 } |
|
378 |
|
379 case EVariantHalCustomRestartReason: |
|
380 { |
|
381 //Restart reason is stored in super page |
|
382 TInt x = (Kern::SuperPage().iHwStartupReason & KHtCustomRestartMask) >> KHtCustomRestartShift ; |
|
383 kumemput32(a1, &x, sizeof(TInt)); |
|
384 break; |
|
385 } |
|
386 |
|
387 case EVariantHalCustomRestart: |
|
388 { |
|
389 if(!Kern::CurrentThreadHasCapability(ECapabilityPowerMgmt,__PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EVariantHalCustomRestart"))) |
|
390 return KErrPermissionDenied; |
|
391 if ((TUint)a1 > KHtCustomRestartMax) |
|
392 return KErrArgument; |
|
393 Kern::Restart((TInt)a1 << KHtCustomRestartShift); |
|
394 } |
|
395 break; |
|
396 |
|
397 case EVariantHalCaseState: |
|
398 { |
|
399 // |
|
400 // TO DO: (optional) |
|
401 // |
|
402 // Read the state of the case, e.g: |
|
403 // TUint32 x = Variant::CaseState(); |
|
404 // kumemput32(a1, &x, sizeof(x)); |
|
405 // |
|
406 break; |
|
407 } |
|
408 |
|
409 case EVariantHalPersistStartupMode: |
|
410 { |
|
411 if (!Kern::CurrentThreadHasCapability(ECapabilityWriteDeviceData,__PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EDisplayHalSetBacklightOn"))) |
|
412 return KErrPermissionDenied; |
|
413 |
|
414 if ((TUint)a1 > KHtRestartStartupModesMax ) // Restart startup mode max value |
|
415 return KErrArgument; |
|
416 // |
|
417 // TO DO: (optional) |
|
418 // |
|
419 // Store the restart reason locally, |
|
420 // which will eventually be picked up by |
|
421 // the power controller, e.g: |
|
422 // iCustomRestartReason = (TUint)a1; |
|
423 break; |
|
424 } |
|
425 |
|
426 |
|
427 case EVariantHalGetPersistedStartupMode: |
|
428 { |
|
429 // |
|
430 // TO DO: (optional) |
|
431 // |
|
432 // Read the restart startup mode, e.g: |
|
433 // TInt startup = (Kern::SuperPage().iHwStartupReason & KHtRestartStartupModesMask) >> KHtRestartStartupModesShift; |
|
434 // kumemput32(a1, &startup, sizeof(TInt)); |
|
435 break; |
|
436 } |
|
437 |
|
438 case EVariantHalGetMaximumCustomRestartReasons: |
|
439 { |
|
440 // |
|
441 // TO DO: (optional) |
|
442 // |
|
443 // Read the maximum custom restart reason, e.g: |
|
444 // kumemput32(a1, &KHtCustomRestartMax, sizeof(TUint)); |
|
445 break; |
|
446 } |
|
447 |
|
448 |
|
449 case EVariantHalGetMaximumRestartStartupModes: |
|
450 { |
|
451 // |
|
452 // TO DO: (optional) |
|
453 // |
|
454 // Read the maximum restart startup mode, e.g: |
|
455 // kumemput32(a1, &KHtRestartStartupModesMax, sizeof(TUint)); |
|
456 break; |
|
457 } |
|
458 |
|
459 case EVariantHalProfilingDefaultInterruptBase: |
|
460 { |
|
461 // |
|
462 // TO DO: (optional) |
|
463 // |
|
464 //Set the default interrupt number for the sampling profiler. |
|
465 //TInt interruptNumber = KIntCpuProfilingDefaultInterruptBase; |
|
466 //kumemput(a1,&interruptNumber,sizeof(interruptNumber)); |
|
467 break; |
|
468 } |
|
469 |
|
470 default: |
|
471 r=KErrNotSupported; |
|
472 break; |
|
473 } |
|
474 return r; |
|
475 } |
|
476 |
|
477 TPtr8 Template::MachineConfiguration() |
|
478 { |
|
479 return TPtr8((TUint8*)&Kern::MachineConfig(),sizeof(TActualMachineConfig),sizeof(TActualMachineConfig)); |
|
480 } |
|
481 |
|
482 TInt Template::VideoRamSize() |
|
483 { |
|
484 // |
|
485 // TO DO: (mandatory) |
|
486 // |
|
487 // Return the size of the area of RAM used to store the Video Buffer, as in the following EXAMPLE ONLY: |
|
488 // |
|
489 return 0x28000; |
|
490 } |
|
491 |
|
492 EXPORT_C void Variant::PowerReset() |
|
493 { |
|
494 // |
|
495 // TO DO: (optional) |
|
496 // |
|
497 // Reset all power supplies |
|
498 // |
|
499 } |
|
500 |
|
501 EXPORT_C TUint Variant::Switches() |
|
502 { |
|
503 // |
|
504 // TO DO: (optional) |
|
505 // |
|
506 // Read the state of on-board switches |
|
507 // |
|
508 return 0; // EXAMPLE ONLY |
|
509 } |
|
510 |
|
511 /****************************************************************************** |
|
512 * Interrupt handling/dispatch |
|
513 ******************************************************************************/ |
|
514 TInt Template::InterruptBind(TInt anId, TIsr anIsr, TAny* aPtr) |
|
515 { |
|
516 TUint id=anId&0x7fffffff; // mask off second-level interrupt mask |
|
517 if (id>=ENumXInts) |
|
518 return KErrArgument; |
|
519 TInt r=KErrNone; |
|
520 SInterruptHandler& h=Handlers[id]; |
|
521 TInt irq=NKern::DisableAllInterrupts(); |
|
522 if (h.iIsr!=Spurious) |
|
523 r=KErrInUse; |
|
524 else |
|
525 { |
|
526 h.iIsr=anIsr; |
|
527 h.iPtr=aPtr; |
|
528 } |
|
529 NKern::RestoreInterrupts(irq); |
|
530 return r; |
|
531 } |
|
532 |
|
533 TInt Template::InterruptUnbind(TInt anId) |
|
534 { |
|
535 TUint id=anId&0x7fffffff; // mask off second-level interrupt mask |
|
536 if (id>=ENumXInts) |
|
537 return KErrArgument; |
|
538 InterruptDisable(anId); |
|
539 InterruptClear(anId); |
|
540 TInt r=KErrNone; |
|
541 SInterruptHandler& h=Handlers[id]; |
|
542 TInt irq=NKern::DisableAllInterrupts(); |
|
543 if (h.iIsr!=Spurious) |
|
544 { |
|
545 h.iIsr=Spurious; |
|
546 h.iPtr=(TAny*)id; |
|
547 } |
|
548 NKern::RestoreInterrupts(irq); |
|
549 return r; |
|
550 } |
|
551 |
|
552 TInt Template::InterruptEnable(TInt anId) |
|
553 { |
|
554 TUint id=anId&0x7fffffff; // mask off second-level interrupt mask |
|
555 if (id>=ENumXInts) |
|
556 return KErrArgument; |
|
557 TInt r=KErrNone; |
|
558 SInterruptHandler& h=Handlers[id]; |
|
559 TInt irq=NKern::DisableAllInterrupts(); |
|
560 if (h.iIsr==Spurious) |
|
561 r=KErrNotReady; |
|
562 else |
|
563 { |
|
564 // |
|
565 // TO DO: (mandatory) |
|
566 // |
|
567 // Enable the hardware interrupt in the source, e.g. |
|
568 // Variant::EnableInt(anId); |
|
569 // |
|
570 } |
|
571 NKern::RestoreInterrupts(irq); |
|
572 return r; |
|
573 } |
|
574 |
|
575 TInt Template::InterruptDisable(TInt anId) |
|
576 { |
|
577 TUint id=anId&0x7fffffff; // mask off second-level interrupt mask |
|
578 if (id>=ENumXInts) |
|
579 return KErrArgument; |
|
580 // |
|
581 // TO DO: (mandatory) |
|
582 // |
|
583 // Disable the hardware interrupt in the source, e.g. |
|
584 // Variant::DisableInt(anId); |
|
585 // |
|
586 return KErrNone; |
|
587 } |
|
588 |
|
589 TInt Template::InterruptClear(TInt anId) |
|
590 { |
|
591 TUint id=anId&0x7fffffff; |
|
592 if (id>=ENumXInts) |
|
593 return KErrArgument; |
|
594 // |
|
595 // TO DO: (mandatory) |
|
596 // |
|
597 // Clear the hardware interrupt in the source, e.g. |
|
598 // Variant::ClearInt(anId); |
|
599 // |
|
600 return KErrNone; |
|
601 } |
|
602 |
|
603 void Template::InitInterrupts() |
|
604 { |
|
605 // Set up the variant interrupt dispatcher |
|
606 |
|
607 // all interrupts initially unbound |
|
608 TInt i; |
|
609 for (i=0; i<(TInt)ENumXInts; i++) |
|
610 { |
|
611 Handlers[i].iPtr=(TAny*)i; |
|
612 Handlers[i].iIsr=Spurious; |
|
613 } |
|
614 |
|
615 // Set up data for 2nd level interrupt dispatcher |
|
616 HandlerData[0]=Variant::BaseLinAddress(); // Linear Base address of 2nd level Int Controller |
|
617 HandlerData[1]=(TUint32)&Handlers[0]; // Pointer to handler array |
|
618 HandlerData[2]=0; // |
|
619 |
|
620 // |
|
621 // TO DO: (mandatory) |
|
622 // |
|
623 // set up ASSP expansion interrupt to generate interrupts whenever a 2nd level interrupt occurrs |
|
624 // |
|
625 |
|
626 // bind Template ASSP expansion interrupt input to our interrupt dispatcher |
|
627 TInt r=Interrupt::Bind(KIntIdExpansion, XIntDispatch, HandlerData); |
|
628 __ASSERT_ALWAYS(r==KErrNone,V_FAULT()); |
|
629 Interrupt::Enable(KIntIdExpansion); // enable expansion interrupt |
|
630 } |
|
631 |
|
632 void Template::Spurious(TAny* aId) |
|
633 { |
|
634 TUint32 id=((TUint32)aId)|0x80000000u; |
|
635 Kern::Fault("SpuriousInt",id); |
|
636 } |
|
637 |
|
638 |
|
639 // USB Client controller |
|
640 |
|
641 TBool Template::UsbClientConnectorDetectable() |
|
642 { |
|
643 __KTRACE_OPT(KHARDWARE, Kern::Printf("Template::UsbClientConnectorDetectable")); |
|
644 |
|
645 // TO DO: The return value should reflect the actual situation. |
|
646 return ETrue; |
|
647 } |
|
648 |
|
649 |
|
650 TBool Template::UsbClientConnectorInserted() |
|
651 { |
|
652 __KTRACE_OPT(KHARDWARE, Kern::Printf("Template::UsbClientConnectorInserted")); |
|
653 |
|
654 // TO DO: Query cable status here. The return value should reflect the actual current state. |
|
655 return ETrue; |
|
656 } |
|
657 |
|
658 |
|
659 TInt Template::RegisterUsbClientConnectorCallback(TInt (*aCallback)(TAny*), TAny* aPtr) |
|
660 { |
|
661 __KTRACE_OPT(KHARDWARE, Kern::Printf("Template::RegisterUsbClientConnectorCallback")); |
|
662 |
|
663 iUsbClientConnectorCallback = aCallback; |
|
664 iUsbClientConnectorCallbackArg = aPtr; |
|
665 |
|
666 // TO DO: Register and enable the interrupt(s) for detecting USB cable insertion/removal here. |
|
667 // (Register UsbClientConnectorIsr.) |
|
668 |
|
669 // TO DO: The return value should reflect the actual situation. |
|
670 return KErrNone; |
|
671 } |
|
672 |
|
673 |
|
674 void Template::UnregisterUsbClientConnectorCallback() |
|
675 { |
|
676 __KTRACE_OPT(KHARDWARE, Kern::Printf("Template::UnregisterUsbClientConnectorCallback")); |
|
677 |
|
678 // TO DO: Disable and unbind the interrupt(s) for detecting USB cable insertion/removal here. |
|
679 |
|
680 iUsbClientConnectorCallback = NULL; |
|
681 iUsbClientConnectorCallbackArg = NULL; |
|
682 } |
|
683 |
|
684 |
|
685 TBool Template::UsbSoftwareConnectable() |
|
686 { |
|
687 __KTRACE_OPT(KHARDWARE, Kern::Printf("Template::UsbSoftwareConnectable")); |
|
688 |
|
689 // TO DO: The return value should reflect the actual situation. |
|
690 return ETrue; |
|
691 } |
|
692 |
|
693 |
|
694 TInt Template::UsbConnect() |
|
695 { |
|
696 __KTRACE_OPT(KHARDWARE, Kern::Printf("Template::UsbConnect")); |
|
697 |
|
698 // TO DO: Do here whatever is necessary for the UDC to appear on the bus (and thus to the host). |
|
699 |
|
700 return KErrNone; |
|
701 } |
|
702 |
|
703 |
|
704 TInt Template::UsbDisconnect() |
|
705 { |
|
706 __KTRACE_OPT(KHARDWARE, Kern::Printf("Template::UsbDisconnect")); |
|
707 |
|
708 // TO DO: Do here whatever is necessary for the UDC to appear disconnected from the bus (and thus from the |
|
709 // host). |
|
710 |
|
711 return KErrNone; |
|
712 } |
|
713 |
|
714 |
|
715 void Template::UsbClientConnectorIsr(TAny *aPtr) |
|
716 // |
|
717 // Services the USB cable interrupt. |
|
718 // |
|
719 { |
|
720 __KTRACE_OPT(KHARDWARE, Kern::Printf("Template::UsbClientConnectorIsr()")); |
|
721 |
|
722 Template* tm = static_cast<Template*>(aPtr); |
|
723 |
|
724 // TO DO: Service interrupt here: determmine cause, clear condition flag (if applicable), etc. |
|
725 |
|
726 if (tm->UsbClientConnectorInserted()) |
|
727 { |
|
728 __KTRACE_OPT(KHARDWARE, Kern::Printf(" > USB cable now inserted.")); |
|
729 } |
|
730 else |
|
731 { |
|
732 __KTRACE_OPT(KHARDWARE, Kern::Printf(" > USB cable now removed.")); |
|
733 } |
|
734 |
|
735 // Important: Inform the USB stack. |
|
736 if (tm->iUsbClientConnectorCallback) |
|
737 { |
|
738 (*tm->iUsbClientConnectorCallback)(tm->iUsbClientConnectorCallbackArg); |
|
739 } |
|
740 } |
|
741 |
|
742 |
|
743 //---eof |