kernel/eka/drivers/pbus/spbus.cpp
changeset 0 a41df078684a
child 13 46fffbe7b5a7
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     1 // Copyright (c) 1998-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 // e32\drivers\pbus\spbus.cpp
       
    15 // 
       
    16 //
       
    17 
       
    18 #include <drivers/pbus.h>
       
    19 
       
    20 const TInt KPBusSocketThreadPriority=26;
       
    21 
       
    22 GLDEF_D DMediaChangeBase* TheMediaChanges[KMaxMediaChanges];
       
    23 GLDEF_D DPBusSocket* TheSockets[KMaxPBusSockets];
       
    24 GLDEF_D DPBusPsuBase* TheVccs[KMaxPBusVccs];
       
    25 GLDEF_D DPBusPsuBase* TheVccCores[KMaxPBusVccs]; 
       
    26 
       
    27 /********************************************
       
    28  * Peripheral bus callback
       
    29  ********************************************/
       
    30 EXPORT_C TPBusCallBack::TPBusCallBack()
       
    31 	:	iSocket(NULL), iFunction(NULL), iIntMask(0), iPtr(NULL)
       
    32 	{
       
    33 	iNext=NULL;
       
    34 	}
       
    35 
       
    36 EXPORT_C TPBusCallBack::TPBusCallBack(TPBusCallBackFn aFunction, TAny* aPtr)
       
    37 	: iSocket(NULL), iFunction(aFunction), iIntMask(0), iPtr(aPtr)
       
    38 	{
       
    39 	iNext=NULL;
       
    40 	}
       
    41 
       
    42 EXPORT_C TPBusCallBack::TPBusCallBack(TPBusIsr anIsr, TAny* aPtr, TUint anIntMask)
       
    43 	: iSocket(NULL), iFunction(NULL), iIntMask(anIntMask), iIsr(anIsr), iPtr(aPtr)
       
    44 	{
       
    45 	iNext=NULL;
       
    46 	}
       
    47 
       
    48 EXPORT_C void TPBusCallBack::Remove()
       
    49 	{
       
    50 	TInt irq=NKern::DisableAllInterrupts();
       
    51 	if (iNext)
       
    52 		Deque();
       
    53 	iNext=NULL;
       
    54 	NKern::RestoreInterrupts(irq);
       
    55 	}
       
    56 
       
    57 EXPORT_C void TPBusCallBack::SetSocket(TInt aSocket)
       
    58 	{
       
    59 	iSocket=TheSockets[aSocket];
       
    60 	}
       
    61 
       
    62 /********************************************
       
    63  * Media change base class
       
    64  ********************************************/
       
    65  
       
    66 /**
       
    67  * Constructor for a DMediaChangeBase object.
       
    68  *
       
    69  * @param aMediaChangeNum The media change number
       
    70  */
       
    71 EXPORT_C DMediaChangeBase::DMediaChangeBase(TInt aMediaChangeNum)
       
    72 	:	iMediaChangeNum(aMediaChangeNum),
       
    73 		iReplyCount(0),
       
    74 		iDoorOpenDfc(DoorOpenDfcFn,this,Kern::DfcQue1(),1)
       
    75 	{
       
    76 	}
       
    77 
       
    78 
       
    79 /**
       
    80  * Creates a DMediaChangeBase object.
       
    81  * This should be overridden at the media and variant layer to allow
       
    82  * interrupts and other media/variant-specific parameters to be initialised.
       
    83  *
       
    84  * Method should be called post object creation, although could be used to
       
    85  * re-initialise parameters.
       
    86  *
       
    87  * @return KErrNone Default
       
    88  */
       
    89 EXPORT_C TInt DMediaChangeBase::Create()
       
    90 	{
       
    91 	return KErrNone;
       
    92 	}
       
    93 
       
    94 /**
       
    95  * Called from ISR triggered by media change or from 
       
    96  * the Peripheral Bus Controller Media Driver context
       
    97  * if a media change is being forced.
       
    98  *
       
    99  * Method adds/enques a media change event on to the door 
       
   100  * open DFC queue. If called by PBUS thread then DFC queue 
       
   101  * is by-passed and change event is dealt with synchronously.
       
   102  *
       
   103  * Media change events are platform specific although are 
       
   104  * generally related to a media door or slot being opened.
       
   105  */
       
   106 EXPORT_C void DMediaChangeBase::DoorOpenService()
       
   107 	{
       
   108 	if (NKern::CurrentContext()==NKern::EInterrupt)
       
   109 		iDoorOpenDfc.Add();
       
   110 	else 
       
   111 		{
       
   112 		if (Kern::DfcQue1()->iThread==(NThreadBase *)NKern::CurrentThread()) 	// check if this is being called from PBUS thread
       
   113 			MediaChangeEvent(ETrue);
       
   114 		else
       
   115 			iDoorOpenDfc.Enque();
       
   116 		}
       
   117 	}
       
   118 
       
   119 
       
   120 /**
       
   121  * High priority DFC triggered by media change interrupt.
       
   122  * 
       
   123  * Media changes events are added/enqued by DMediaChangeBase::DoorOpenService().
       
   124  * 
       
   125  * @param aPtr Pointer to an instantiated class which enqued/added this DFC event
       
   126  */
       
   127 void DMediaChangeBase::DoorOpenDfcFn(TAny* aPtr)
       
   128 	{
       
   129 	DMediaChangeBase* pM=(DMediaChangeBase*)aPtr;
       
   130 	pM->MediaChangeEvent(ETrue);
       
   131 	}
       
   132 
       
   133 /**
       
   134  *
       
   135  * Notifies sockets of door close event.
       
   136  *
       
   137  * This function must be called by variant when door close has been detected.
       
   138  */
       
   139 EXPORT_C void DMediaChangeBase::DoorClosedService()
       
   140 	{
       
   141 	MediaChangeEvent(EFalse);
       
   142 	}
       
   143 
       
   144 /**
       
   145  * Notifies relevant peripheral bus sockets of door open or close events.
       
   146  *
       
   147  * @param aDoorOpened  ETrue if door is opened
       
   148  *
       
   149  * @see DPBusSocket::DPBusSocket
       
   150  */
       
   151 void DMediaChangeBase::MediaChangeEvent(TBool aDoorOpened)
       
   152 	{
       
   153 	__KTRACE_OPT(KPBUS1,Kern::Printf(">DMediaChangeBase(%d)::MediaChangeEvent(%d)",iMediaChangeNum,aDoorOpened));
       
   154 	TInt i;
       
   155 
       
   156 	// notify all sockets affected
       
   157 	for (i=0; i<KMaxPBusSockets; i++)
       
   158 		{
       
   159 		DPBusSocket* pS=TheSockets[i];
       
   160 		if (pS && pS->iMediaChange==this)
       
   161 			{
       
   162 			// Only increment base reply count if actually adding a DFC
       
   163 			if (!pS->iMediaChangeDfc.Queued())
       
   164 			    __e32_atomic_add_ord32(&iReplyCount, 1);
       
   165 			pS->MediaChangeEvent(aDoorOpened);
       
   166 			}
       
   167 		}
       
   168 	}
       
   169 
       
   170 /**
       
   171  * To be called by peripheral bus socket derived classes when
       
   172  * door open/close event has been processed.
       
   173  *
       
   174  * @param aDoorOpened   ETrue door opened event processed,
       
   175  *                      EFalse door closed event processed
       
   176  *
       
   177  * @see DPBusSocket::DoorOpenEvent()
       
   178  * @see DPBusSocket::DoorCloseEvent()
       
   179  */
       
   180 void DMediaChangeBase::AcknowledgeEvent(TBool aDoorOpened)
       
   181 	{
       
   182 	TInt c = __e32_atomic_tas_ord32(&iReplyCount, 1, -1, 0);
       
   183 	if (c==1)
       
   184 		{
       
   185 		if (aDoorOpened)
       
   186 			DoDoorOpen();
       
   187 		else
       
   188 			DoDoorClosed();
       
   189 		}
       
   190 	}
       
   191 
       
   192 /********************************************
       
   193  * Power supply base class
       
   194  ********************************************/
       
   195 void psuTick(TAny* aPtr)
       
   196 	{
       
   197 	DPBusPsuBase* pP=(DPBusPsuBase*)aPtr;
       
   198 	pP->iPsuDfc.Enque();
       
   199 	}
       
   200 	
       
   201 void psuDfc(TAny* aPtr)
       
   202 	{
       
   203 	DPBusPsuBase* pP=(DPBusPsuBase*)aPtr;
       
   204 	pP->DoTickService();
       
   205 	}
       
   206 
       
   207 /**
       
   208 Constructor for a DPBusPsuBase object.
       
   209 
       
   210 @param aPsuNum Unique power supply identification number
       
   211 @param aMediaChangedNum Unique media change identification number
       
   212 */
       
   213 DPBusPsuBase::DPBusPsuBase(TInt aPsuNum, TInt aMediaChangeNum)
       
   214 	: iPsuNum(aPsuNum), iMediaChangeNum(aMediaChangeNum), iVoltCheckMethod(EPsuChkComparator), iState(EPsuOff),
       
   215 	iPsuDfc(psuDfc, this, 4),
       
   216 	iPwrDownCheckFn(DoPwrDownCheck)
       
   217 	{
       
   218 //	iCurrLimited=EFalse;
       
   219 //	iVoltageSupported=0;
       
   220 //	iMaxCurrentInMicroAmps=0;
       
   221 //	iVoltCheckInterval=0;
       
   222 //	iInactivityCount=0;
       
   223 //	iNotLockedCount=0;
       
   224 //	iInactivityTimeout=0;
       
   225 //	iNotLockedTimeout=0;
       
   226 	}
       
   227 
       
   228 void DPBusPsuBase::DoPwrDownCheck(TAny* aPtr)
       
   229 	{
       
   230 	DPBusPsuBase& self = *static_cast<DPBusPsuBase*>(aPtr);
       
   231 	self.PwrDownCheck();
       
   232 	}
       
   233 
       
   234 /**
       
   235 Initialises a DPBusPsuBase object.
       
   236 
       
   237 Sets object information based on hardware variant PSU inforamtion.
       
   238 Calls DoCreate to initialise the PSU.
       
   239 
       
   240 @return Standard Symbian OS error code.
       
   241 
       
   242 @see DPBusPsuBase::PsuInfo()
       
   243 @see DPBusPsuBase::DoCreate()
       
   244 */
       
   245 TInt DPBusPsuBase::Create()
       
   246 	{
       
   247 
       
   248 	TPBusPsuInfo pi;
       
   249 	PsuInfo(pi);
       
   250 	iVoltageSupported=pi.iVoltageSupported;
       
   251 	iMaxCurrentInMicroAmps=pi.iMaxCurrentInMicroAmps;
       
   252 	iVoltCheckInterval=pi.iVoltCheckInterval;
       
   253 	iVoltCheckMethod=pi.iVoltCheckMethod;
       
   254 	iInactivityTimeout=pi.iInactivityTimeOut;
       
   255 	iNotLockedTimeout=pi.iNotLockedTimeOut;
       
   256 
       
   257 	TInt r=DoCreate();
       
   258 	if (r!=KErrNone)
       
   259 		return r;
       
   260 	
       
   261 	iPsuDfc.SetDfcQ(&iSocket->iDfcQ);
       
   262 	
       
   263 	return KErrNone;
       
   264 	}
       
   265 
       
   266 
       
   267 /**
       
   268 Initialises the power supply unit.
       
   269 
       
   270 The function is provided by the hardware variant layer, and needs to initialise 
       
   271 interrupts and other variant-specific parameters.
       
   272 
       
   273 The default implementation returns KErrNone.
       
   274 
       
   275 @return KErrNone
       
   276 */
       
   277 EXPORT_C TInt DPBusPsuBase::DoCreate()
       
   278 	{
       
   279 	return KErrNone;
       
   280 	}
       
   281 
       
   282 
       
   283 /**
       
   284 Reset (turn off) the power supply unit.
       
   285 Sets PSU state to EPsuOff.
       
   286 */
       
   287 void DPBusPsuBase::Reset()
       
   288 	{
       
   289 	SetState(EPsuOff);
       
   290 	iCurrLimited=EFalse;
       
   291 	}
       
   292 
       
   293 
       
   294 /**
       
   295 Checks whether this PSU is powering a bus containing
       
   296 a locked device, i.e. one that is recognised and in use by a client.
       
   297 
       
   298 The function is provided at the media layer, could be used to ensure power is not
       
   299 removed whilst media is locked or some other media specific power management activatity.
       
   300 
       
   301 The default implementation just returns EFalse.
       
   302 
       
   303 @return EFalse
       
   304 */
       
   305 EXPORT_C TBool DPBusPsuBase::IsLocked()
       
   306 	{
       
   307 	return EFalse;
       
   308 	}
       
   309 
       
   310 /**
       
   311 Controls the power supply state.
       
   312 
       
   313 @param aState A TPBusPsuState enumeration specifying the required state
       
   314 			 (EPsuOnFull, EPsuOff, EPsuOnCurLimit)
       
   315 
       
   316 @return KErrNone if successful, otherwise one of the other system wide error codes.
       
   317 
       
   318 @see TPBusPsuState
       
   319 @see DPBusPsuBase::DoSetState()
       
   320 */
       
   321 EXPORT_C TInt DPBusPsuBase::SetState(TPBusPsuState aState)
       
   322 	{
       
   323 
       
   324 	TInt r=KErrGeneral;
       
   325 	if (aState==EPsuOff)
       
   326 		{
       
   327 		iTickLink.Cancel(); // No point in having the 1 second tick running while the PSU is off
       
   328 		}
       
   329 	else
       
   330 		{
       
   331 		// Start the 1 second tick to monitor for inactivity, not in use and PSU level checking
       
   332 		iTickLink.Cancel();
       
   333 		iTickLink.Periodic(KPBusPsuTickInterval,psuTick,this);
       
   334 		}
       
   335 
       
   336 	// Don't turn the PSU back on if it has current limited since the last reset event 
       
   337 	iInactivityCount=0;
       
   338 	iNotLockedCount=0;
       
   339 	if (aState==EPsuOff || !iCurrLimited)
       
   340 		{
       
   341 		DoSetState(aState);
       
   342 		iState=aState;
       
   343 		r=KErrNone;
       
   344 		}
       
   345 	__KTRACE_OPT(KPBUS2,Kern::Printf("<Psu(%d):Set(%d)-%d",iPsuNum,aState,r));
       
   346 	return r;
       
   347 	}
       
   348 
       
   349 
       
   350 /**
       
   351 Check the voltage level of the power supply unit is as expected.
       
   352 This method is called every PSU tick.
       
   353 
       
   354 @param aCheckStatus Power check status in which voltage check can be performed (e.g. KPsuChkOnPwrUp).
       
   355 
       
   356 @return KErrNone Voltage checking has been performed.
       
   357         KErrNotSupported Voltage checking is not supported by the hardware variant.
       
   358         
       
   359 @see KPsuChkOnPwrUp       
       
   360 @see KPsuChkWhileOn
       
   361 @see DPBusPsuBase::DoTickService()
       
   362 @see DPBusPsuBase::DoCheckVoltage()
       
   363 */
       
   364 TInt DPBusPsuBase::CheckVoltage(TUint aCheckStatus)
       
   365 	{
       
   366 	// Check that voltage checking is in order at this time
       
   367 	if (
       
   368 		(aCheckStatus&iVoltCheckInterval) &&
       
   369 		((aCheckStatus&KPsuChkOnPwrUp) || ((aCheckStatus&KPsuChkWhileOn)&&iState==EPsuOnFull))
       
   370 	   )
       
   371 		{
       
   372 		DoCheckVoltage();
       
   373 		return KErrNone;
       
   374 		}
       
   375 	return KErrNotSupported;
       
   376 	}
       
   377 
       
   378 
       
   379 /**
       
   380 Reports the result of the voltage check.
       
   381 
       
   382 The function is called by the variant implementation of DoCheckVoltage() 
       
   383 to report the result.
       
   384 
       
   385 Reporting a result of KErrGeneral (to indicate a failure) will result in a 
       
   386 call to DPBusSocket::PsuFault(), otherwise report KErrNone to indicate a pass
       
   387 and KErrNotReady if the voltage check was not completed.
       
   388 
       
   389 @param anError System wide error code
       
   390 
       
   391 @see DPBusPsuBase::DoCheckVoltage()
       
   392 @see DPBusSocket::PsuFault()
       
   393 */
       
   394 EXPORT_C void DPBusPsuBase::ReceiveVoltageCheckResult(TInt anError)
       
   395 	{
       
   396 //	__KTRACE_OPT(KPBUS1,Kern::Printf("DPBusPsuBase(%d)::ReceiveVoltageCheckResult(%d)",iPsuNum,anError));
       
   397 	if (anError==KErrGeneral)
       
   398 		{
       
   399 		SetCurrLimited();
       
   400 		iSocket->PsuFault(KErrCorrupt);
       
   401 		}
       
   402 	}
       
   403 
       
   404 /**
       
   405 Get the current power supply unit status
       
   406 
       
   407 @return PSU status.
       
   408 
       
   409 @see TPBusPsuStatus
       
   410 */
       
   411 TPBusPsuStatus DPBusPsuBase::Status()
       
   412 	{
       
   413 	if (iCurrLimited)
       
   414 		return(EPsuStatError);
       
   415 	else
       
   416 		return( (iState==EPsuOff) ? EPsuStatOff : EPsuStatOn );
       
   417 	}
       
   418 
       
   419 
       
   420 /**
       
   421 Checks if power supply unit can be turned off.
       
   422 
       
   423 @see DPBusPsuBase::DoTickService()
       
   424 */
       
   425 void DPBusPsuBase::PwrDownCheck()
       
   426 	{
       
   427 
       
   428 	if (
       
   429 		(iNotLockedTimeout&&!IsLocked()&&++iNotLockedCount>iNotLockedTimeout) ||
       
   430 		(iInactivityTimeout&&++iInactivityCount>iInactivityTimeout)
       
   431 	   )
       
   432 			iSocket->PsuTimeout();
       
   433 	}
       
   434 	
       
   435 	
       
   436 /**
       
   437 Services the Pc Card Tick (called in timer thread).
       
   438 */
       
   439 EXPORT_C void DPBusPsuBase::DoTickService()
       
   440 	{
       
   441 	if (iPwrDownCheckFn)
       
   442 		(*iPwrDownCheckFn)(this);	
       
   443 	CheckVoltage(KPsuChkWhileOn);	// Check voltage level
       
   444 	}
       
   445 
       
   446 
       
   447 /********************************************
       
   448  * Peripheral bus power handler
       
   449  ********************************************/
       
   450 DPBusPowerHandler::DPBusPowerHandler(DPBusSocket* aSocket)
       
   451 	:	DPowerHandler(*aSocket->iName),
       
   452 		iSocket(aSocket)
       
   453 	{
       
   454 	}
       
   455 
       
   456 void DPBusPowerHandler::PowerUp()
       
   457 	{
       
   458 	iSocket->iPowerUpDfc.Enque();
       
   459 	}
       
   460 
       
   461 void DPBusPowerHandler::PowerDown(TPowerState)
       
   462 	{
       
   463 	iSocket->iPowerDownDfc.Enque();
       
   464 	}
       
   465 
       
   466 /********************************************
       
   467  * Peripheral bus socket base class
       
   468  ********************************************/
       
   469 void mediaChangeDfc(TAny* aPtr)
       
   470 	{
       
   471 	DPBusSocket* pS=(DPBusSocket*)aPtr;
       
   472 	if (pS->iDoorOpened)
       
   473 		pS->DoorOpenEvent();
       
   474 	else
       
   475 		pS->DoorCloseEvent();
       
   476 	}
       
   477 
       
   478 void powerUpDfc(TAny* aPtr)
       
   479 	{
       
   480 	DPBusSocket* pS=(DPBusSocket*)aPtr;
       
   481 	pS->DoPowerUp();
       
   482 	}
       
   483 
       
   484 void powerDownDfc(TAny* aPtr)
       
   485 	{
       
   486 	DPBusSocket* pS=(DPBusSocket*)aPtr;
       
   487 	pS->DoPowerDown();
       
   488 	}
       
   489 
       
   490 	/**
       
   491     PBus Socket panics. Faults the system. 
       
   492 	This will start the Crash Debugger if it is present, otherwise the system is rebooted by calling Kern::Restart(0)
       
   493 	@param aPanic	The panic to be raised
       
   494 	@see DPBusSocket::TPanic
       
   495 	*/
       
   496 EXPORT_C void DPBusSocket::Panic(DPBusSocket::TPanic aPanic)
       
   497 	{
       
   498 	Kern::Fault("PBUS",aPanic);
       
   499 	}
       
   500 
       
   501 	/**
       
   502     Flags the media driver as entering a critical part of its processing.
       
   503     In this context, critical means that the driver must be allowed to complete its current activity.
       
   504 	
       
   505 	@return	KErrNone if successful,
       
   506 			KErrNotReady if there is any postponed events outstanding.
       
   507 	@see DPBusSocket::EndInCritical()
       
   508 	*/
       
   509 EXPORT_C TInt DPBusSocket::InCritical()
       
   510 	{
       
   511 	__KTRACE_OPT(KPBUS1,Kern::Printf(">DPBusSocket(%d)::InCritical",iSocketNumber));
       
   512 	if (iPostponeCount==0 && iPostponedEvents!=0)
       
   513 		return KErrNotReady;	// we are about to do media change/power down
       
   514 	++iPostponeCount;
       
   515 	return KErrNone;
       
   516 	}
       
   517 
       
   518 	/**
       
   519     Flags the media driver as leaving a critical part of its processing.
       
   520 	This function enque the media change DFC or power down DFC depending on the event DPBusSocket::iPostponedEvents.
       
   521 	@see TPostponedEvent
       
   522 	@see DPBusSocket::InCritical()
       
   523 	*/
       
   524 EXPORT_C void DPBusSocket::EndInCritical()
       
   525 	{
       
   526 	__KTRACE_OPT(KPBUS1,Kern::Printf(">DPBusSocket(%d)::EndInCritical",iSocketNumber));
       
   527 	if (iPostponeCount && --iPostponeCount==0)
       
   528 		{
       
   529 		if (iPostponedEvents & EMediaChange)
       
   530 			{
       
   531 			iMediaChangeDfc.Enque();
       
   532 			__KTRACE_OPT(KPBUS1,Kern::Printf("Media change - done postponed"));
       
   533 			}
       
   534 		if (iPostponedEvents & EPowerDown)
       
   535 			{
       
   536 			iPowerDownDfc.Enque();
       
   537 			__KTRACE_OPT2(KPBUS1,KPOWER,Kern::Printf("Power down - done postponed"));
       
   538 			}
       
   539 		}
       
   540 	}
       
   541 
       
   542 	/**
       
   543 	Sets the incremental value of current consumption to aCurrent.
       
   544     @param	aCurrent	Delta Current in Milliamps 
       
   545 	@see DPowerHandler::DeltaCurrentConsumption()
       
   546 	*/
       
   547 EXPORT_C void DPBusSocket::DeltaCurrentConsumption(TInt aDelta)
       
   548 	{
       
   549 	iPowerHandler->DeltaCurrentConsumption(aDelta);
       
   550 	}
       
   551 
       
   552 	/**
       
   553 	Constructor for DPBusSocket.
       
   554 	Sets the iSocketNumber and initializes the DFC queue for Media Change Dfc, PowerUp Dfc, PowerDown Dfc and PSU Dfc queue.
       
   555     @param	aSocketNumber Pbus socket number
       
   556 	*/
       
   557 DPBusSocket::DPBusSocket(TInt aSocketNumber)
       
   558 	:	iSocketNumber(aSocketNumber),
       
   559 		iMediaChangeDfc(mediaChangeDfc, this, 6),
       
   560 		iPowerUpDfc(powerUpDfc, this, 4),
       
   561 		iPowerDownDfc(powerDownDfc, this, 4),
       
   562 		iPsuDfc(psuDfc, this, 4)
       
   563 	{
       
   564 //	iPowerGroup=0;
       
   565 //	iName=NULL;
       
   566 //	iState=EPBusCardAbsent;
       
   567 //	iPostponeCount=0;
       
   568 //	iPostponedEvents=0;
       
   569 //	iPowerHandler=NULL;
       
   570 	}
       
   571 
       
   572 	/**
       
   573 	Creates a new Socket.
       
   574 	This method sets the DFC Queue for the driver associated,
       
   575     Constructs power handler and registers it with the Power Manager.
       
   576 	@param  aName	Assigns aName to the PBus socket.
       
   577 	@return KErrNone	if successful, otherwise one of the other system wide error codes.
       
   578 	@see DPBusPowerHandler
       
   579 	@see iMediaChangeDfc
       
   580 	@see iPowerUpDfc
       
   581 	@see iPowerDownDfc
       
   582 	@see iPsuDfc
       
   583 	*/
       
   584 TInt DPBusSocket::Create(const TDesC* aName)
       
   585 	{
       
   586 	__KTRACE_OPT(KPBUS1,Kern::Printf(">DPBusSocket(%d)::Create %lS",iSocketNumber,aName));
       
   587 	iName=aName;
       
   588 	DPBusPowerHandler* pH=new DPBusPowerHandler(this);
       
   589 	if (!pH)
       
   590 		return KErrNoMemory;
       
   591 	iPowerHandler=pH;
       
   592 	pH->Add();		// register power handler
       
   593 	TInt r=Kern::DfcQInit(&iDfcQ, KPBusSocketThreadPriority, iName);
       
   594 	if (r!=KErrNone)
       
   595 		return r;
       
   596 	iMediaChangeDfc.SetDfcQ(&iDfcQ);
       
   597 	iPowerUpDfc.SetDfcQ(&iDfcQ);
       
   598 	iPowerDownDfc.SetDfcQ(&iDfcQ);
       
   599 	
       
   600 	return KErrNone;
       
   601 	}
       
   602 
       
   603 	/**
       
   604 	Initializes the PBus socket by changing its state to EPBusOff.
       
   605 	@return	KErrNone	if successful,
       
   606 			otherwise one of the other system wide error codes.
       
   607 	*/
       
   608 TInt DPBusSocket::Init()
       
   609 	{
       
   610 	__KTRACE_OPT(KPBUS1,Kern::Printf(">DPBusSocket(%d)::Init",iSocketNumber));
       
   611 	__PM_ASSERT(iState == EPBusCardAbsent);
       
   612 	if (MediaState()==EDoorClosed && CardIsPresent())
       
   613 		ChangeState(EPBusOff,KErrNotReady);
       
   614 	return KErrNone;
       
   615 	}
       
   616 
       
   617 void DPBusSocket::ResetSocket(TBool aFullReset)
       
   618 	{
       
   619 	Reset1();
       
   620 	iVcc->Reset();
       
   621 	if (aFullReset)
       
   622 		Reset2();
       
   623 	}
       
   624 
       
   625 void DPBusSocket::ChangeState(TInt aState, TInt anError)
       
   626 //
       
   627 // Change state, notifying all clients
       
   628 //
       
   629 	{
       
   630 	__KTRACE_OPT(KPBUS1,Kern::Printf("Socket %d ChangeState %d to %d, err %d",iSocketNumber,iState,aState,anError));
       
   631 	if (iState!=aState)
       
   632 		{
       
   633 		if(iState == EPBusCardAbsent && aState == EPBusOff && anError == KErrTimedOut)
       
   634 			{
       
   635 			// Maintain the internal state to EPBusCardAbsent when PSU
       
   636 			// times out to prevent the media from being powered back up.
       
   637 			}
       
   638 		else
       
   639 			{
       
   640 			iState=aState;
       
   641 			}
       
   642 
       
   643 		// notify all clients of state change
       
   644 		SDblQueLink* pC=iCallBackQ.iA.iNext;
       
   645 		while (pC && pC!=&iCallBackQ.iA)
       
   646 			{
       
   647 			((TPBusCallBack*)pC)->NotifyPBusStateChange(aState,anError);
       
   648 			pC=pC->iNext;
       
   649 			}
       
   650 		}
       
   651 	}
       
   652 
       
   653 void DPBusSocket::Isr(TInt anId)
       
   654 //
       
   655 // Service a card interrupt
       
   656 //
       
   657 	{
       
   658 	// notify all interested clients of interrupt
       
   659 	SDblQueLink* pC=iCallBackQ.iA.iNext;
       
   660 #ifdef _DEBUG
       
   661 	TInt n=0;
       
   662 #endif
       
   663 	while (pC!=&iCallBackQ.iA)
       
   664 		{
       
   665 #ifdef _DEBUG
       
   666 		n++;
       
   667 #endif
       
   668 		((TPBusCallBack*)pC)->Isr(anId);
       
   669 		pC=pC->iNext;
       
   670 		}
       
   671 #ifdef _DEBUG
       
   672 	__KTRACE_OPT(KPBUS1,Kern::Printf("!%d",n));
       
   673 #endif
       
   674 	}
       
   675 
       
   676 	/**
       
   677 	This function adds a callback function to the socket.
       
   678 	@param aCallBack is a pointer to PBus callback function for event notification.
       
   679 	@see TPBusCallBack
       
   680 	*/
       
   681 EXPORT_C void DPBusSocket::Add(TPBusCallBack* aCallBack)
       
   682 	{
       
   683 	__KTRACE_OPT(KPBUS1,Kern::Printf("DPBusSocket(%d)::Add(%08x) next %08x",iSocketNumber,aCallBack,aCallBack->iNext));
       
   684 	TInt irq=NKern::DisableAllInterrupts();
       
   685 	if (!aCallBack->iNext)
       
   686 		iCallBackQ.Add(aCallBack);
       
   687 	NKern::RestoreInterrupts(irq);
       
   688 	}
       
   689 
       
   690 	/**
       
   691 	Called by clients to power up the socket.
       
   692 	@return	KErrNone	if successful, otherwise one of the other system-wide error codes including: 
       
   693 				KErrNotReady if card absent or media change has occurred,
       
   694 				KErrServerBusy if already powering up,
       
   695 				KErrCompletion if already powered up,
       
   696 				KErrCorrupt if PSU fault occurs.
       
   697 
       
   698     @panic PBUS 1, if PBUS state is invalid.
       
   699 	@see TPBusState
       
   700 	*/
       
   701 EXPORT_C TInt DPBusSocket::PowerUp()
       
   702 	{
       
   703 	__KTRACE_OPT2(KPBUS1,KPOWER,Kern::Printf(">DPBusSocket(%d)::PowerUp state %d",iSocketNumber,iState));
       
   704 	TInt r=KErrNone;
       
   705 	switch (iState)
       
   706 		{
       
   707 		case EPBusCardAbsent:		// card absent or media change has occurred
       
   708 			r=KErrNotReady;
       
   709 			break;
       
   710 		case EPBusOff:
       
   711 			break;
       
   712 		case EPBusPoweringUp:		// already powering up
       
   713 		case EPBusPowerUpPending:
       
   714 			r=KErrServerBusy;
       
   715 			break;
       
   716 		case EPBusOn:				// already powered up
       
   717 			r=KErrCompletion;
       
   718 			break;
       
   719 		case EPBusPsuFault:
       
   720 			r=KErrCorrupt;
       
   721 			break;
       
   722 		default:
       
   723 			Panic(EPowerUpInvalidState);
       
   724 		}
       
   725 	if (r==KErrNone)
       
   726 		{
       
   727 		if (iStandby)
       
   728 			{
       
   729 			// machine is powering down, so delay client until machine powers back up
       
   730 			// remember to power up when machine powers back up
       
   731 			ChangeState(EPBusPowerUpPending,KErrNone);
       
   732 			}
       
   733 		else
       
   734 			{
       
   735 			ChangeState(EPBusPoweringUp,KErrNone);
       
   736 			InitiatePowerUpSequence();
       
   737 			}
       
   738 		}
       
   739 	__KTRACE_OPT2(KPBUS1,KPOWER,Kern::Printf("<DPBusSocket(%d)::PowerUp ret %d, state %d",iSocketNumber,r,iState));
       
   740 	return r;
       
   741 	}
       
   742 	/**
       
   743 	This function is called upon completion of the power up sequence of the device.
       
   744 	This is method is called by the derived class methods to terminate the powerup sequence with error codes.
       
   745 
       
   746 	@param anError	One of the system wide error codes.
       
   747 	@see DPBusSocket::InitiatePowerUpSequence()
       
   748 	*/
       
   749 
       
   750 EXPORT_C void DPBusSocket::PowerUpSequenceComplete(TInt anError)
       
   751 	{
       
   752 	__KTRACE_OPT2(KPBUS1,KPOWER,Kern::Printf("DPBusSocket(%d)::PowerUpSequenceComplete state %d error %d",iSocketNumber,iState,anError));
       
   753 	if (iState!=EPBusCardAbsent && iState!=EPBusOff)
       
   754 		{
       
   755 		if (anError==KErrNone)
       
   756 			ChangeState(EPBusOn,KErrNone);
       
   757 		else if (anError==KErrBadPower || anError==KErrAbort || anError==KErrTimedOut)
       
   758 			ChangeState(EPBusOff,anError);
       
   759 		else if (anError == KErrNotReady)
       
   760 			ChangeState(EPBusCardAbsent,KErrAbort);
       
   761 		else
       
   762 			ChangeState(EPBusPsuFault,anError);
       
   763 		}
       
   764 	}
       
   765 
       
   766 void DPBusSocket::PsuFault(TInt anError)
       
   767 	{
       
   768 	__KTRACE_OPT(KPBUS1,Kern::Printf(">DPBusSocket(%d)::PsuFault state %d error %d",iSocketNumber,iState,anError));
       
   769 	ResetSocket(ETrue);
       
   770 	ChangeState(EPBusPsuFault,anError);
       
   771 	}
       
   772 
       
   773 void DPBusSocket::PsuTimeout()
       
   774 	{
       
   775 	__KTRACE_OPT(KPBUS1,Kern::Printf(">DPBusSocket(%d)::PsuTimeout state %d",iSocketNumber,iState));
       
   776 	ResetSocket(EFalse);
       
   777 	ChangeState(EPBusOff,KErrTimedOut);
       
   778 	}
       
   779 
       
   780 void DPBusSocket::DoPowerUp()
       
   781 //
       
   782 // Called on transition from standby
       
   783 //
       
   784 	{
       
   785 	__KTRACE_OPT2(KPBUS1,KPOWER,Kern::Printf("DPBusSocket(%d)::DoPowerUp state %d",iSocketNumber,iState));
       
   786 	__PM_ASSERT(iStandby);
       
   787 	if (iState!=EPBusCardAbsent && iState!=EPBusOff && iState!=EPBusPowerUpPending)
       
   788 		Panic(EMcPowerUpInvalidState);
       
   789 
       
   790 	// when we power up, check whether the door is closed and a card is present
       
   791 	// if so we should start in state Off otherwise in state CardAbsent
       
   792 
       
   793 	TMediaState doorState = MediaState();
       
   794 	TBool cardIsPresent = CardIsPresent();
       
   795 
       
   796 #ifdef __ENABLE_SIMULATED_MEDIA_CHANGE
       
   797 	// Override the default media state is we are simulating media change
       
   798 	if(iSimulatedMediaState != DPBusSocket::EPeriphBusMediaNormal)
       
   799 		{
       
   800 		doorState     = (iSimulatedMediaState == DPBusSocket::EPeriphBusDoorOpen) ? EDoorOpen : EDoorClosed;
       
   801 		cardIsPresent = (iSimulatedMediaState == DPBusSocket::EPeriphBusMediaPresent);
       
   802 		}
       
   803 #endif
       
   804 
       
   805 	if (!(doorState==EDoorClosed && cardIsPresent))
       
   806 		ChangeState(EPBusCardAbsent,KErrNotReady);
       
   807 	else if (iState==EPBusPowerUpPending)
       
   808 		{
       
   809 		// if a power-up request is pending, process it now
       
   810 		ChangeState(EPBusPoweringUp,KErrNone);
       
   811 		InitiatePowerUpSequence();
       
   812 		}
       
   813 	else
       
   814 		ChangeState(EPBusOff,KErrNotReady);
       
   815 	iStandby = EFalse;
       
   816 	iPowerHandler->PowerUpDone();
       
   817 	}
       
   818 
       
   819 void DPBusSocket::DoPowerDown()
       
   820 //
       
   821 // Called by DPowerManager on transition to standby
       
   822 //
       
   823 	{
       
   824 	__KTRACE_OPT2(KPBUS1,KPOWER,Kern::Printf("DPBusSocket(%d)::DoPowerDown state %d",iSocketNumber,iState));
       
   825 	__PM_ASSERT(!iStandby);
       
   826 	if (iPostponeCount)
       
   827 		{
       
   828 		iPostponedEvents |= EPowerDown;
       
   829 		__KTRACE_OPT(KPBUS1,Kern::Printf("Power down postponed"));
       
   830 		return;
       
   831 		}
       
   832 	iPostponedEvents &= ~EPowerDown;
       
   833 	switch (iState)
       
   834 		{
       
   835 		case EPBusPoweringUp:
       
   836 		case EPBusOn:
       
   837 		case EPBusPsuFault:
       
   838 			ChangeState(EPBusOff,KErrNone);
       
   839 		case EPBusCardAbsent:
       
   840 		case EPBusOff:
       
   841 		case EPBusPowerUpPending:
       
   842 			break;
       
   843 		default:
       
   844 			Panic(EEmergencyPowerDownInvalidState);
       
   845 		}
       
   846 		
       
   847 	if(iRequestPowerDownCount == 0)
       
   848 		{
       
   849 		ResetSocket(EFalse);
       
   850 		iStandby = ETrue;
       
   851 		iPowerHandler->PowerDownDone();
       
   852 		}
       
   853 	}
       
   854 
       
   855 	/**
       
   856 	Notifies the socket that we are deferring this power down event. 
       
   857 	The function increments the iRequestPowerDownCount reference count
       
   858 	@see DPBusSocket::PowerDownComplete()
       
   859 	*/
       
   860 EXPORT_C void DPBusSocket::RequestAsyncPowerDown()
       
   861 	{
       
   862 	__KTRACE_OPT(KPBUS1,Kern::Printf("DPBusSocket::RequestAsyncPowerDown"));	
       
   863     __e32_atomic_add_ord32(&iRequestPowerDownCount, 1);
       
   864 	__KTRACE_OPT(KPBUS1,Kern::Printf("   >> count=%d", iRequestPowerDownCount));
       
   865 	}
       
   866 
       
   867 	/**
       
   868 	This function power down the PBus. Powers down the PBus if iRequestPowerDownCount is equal to 1.
       
   869 	@see DPBusSocket::RequestAsyncPowerDown()
       
   870 	@see iRequestPowerDownCount
       
   871 	*/
       
   872 EXPORT_C void DPBusSocket::PowerDownComplete()
       
   873 	{
       
   874 	__KTRACE_OPT(KPBUS1,Kern::Printf("DPBusSocket::PowerDownComplete"));
       
   875 	if (__e32_atomic_tas_ord32(&iRequestPowerDownCount, 1, -1, 0) == 1)
       
   876 		{
       
   877 		__KTRACE_OPT(KPBUS1,Kern::Printf("   > Signalling Power Down (deferred)"));
       
   878 		DoPowerDown();
       
   879 		}
       
   880 	__KTRACE_OPT(KPBUS1,Kern::Printf("   >> count=%d", iRequestPowerDownCount));
       
   881 	}
       
   882 	
       
   883 	/**
       
   884 	This function is called by the local media device driver to force a remount of the media device.
       
   885 	@see DMediaChangeBase::ForceMediaChange()
       
   886 	*/
       
   887 EXPORT_C void DPBusSocket::ForceMediaChange()
       
   888 	{
       
   889 	iMediaChange->ForceMediaChange();
       
   890 	}
       
   891 
       
   892 void DPBusSocket::MediaChangeEvent(TBool aDoorOpened)
       
   893 //
       
   894 // Called in high-priority DFC
       
   895 //
       
   896 	{
       
   897 	__KTRACE_OPT(KPBUS1,Kern::Printf(">DPBusSocket(%d)::MediaChangeEvent %d state %d",iSocketNumber,aDoorOpened,iState));
       
   898 	iDoorOpened=aDoorOpened;
       
   899 	iMediaChangeDfc.Enque();
       
   900 	}
       
   901 
       
   902 void DPBusSocket::DoorOpenEvent()
       
   903 //
       
   904 // Called in socket thread
       
   905 //
       
   906 	{
       
   907 	__KTRACE_OPT(KPBUS1,Kern::Printf(">DPBusSocket(%d)::DoorOpenEvent state %d",iSocketNumber,iState));
       
   908 
       
   909 	if (iPostponeCount)
       
   910 		{
       
   911 		iPostponedEvents |= EMediaChange;
       
   912 		__KTRACE_OPT(KPBUS1,Kern::Printf("Media change postponed"));
       
   913 		return;
       
   914 		}
       
   915 	iPostponedEvents &= ~EMediaChange;
       
   916 
       
   917     // notify all clients of media change
       
   918 	ChangeState(EPBusCardAbsent,KErrNotReady);
       
   919 	
       
   920 	// power down the socket
       
   921 	ResetSocket(ETrue);
       
   922 
       
   923 	// get the media state befor calling AcknowledgeEvent() as the PSL may start a debounce 
       
   924 	// timer on this call and return EDoorOpen while the timer is active....
       
   925 	TMediaState mediaState = MediaState();
       
   926 
       
   927 #ifdef __ENABLE_SIMULATED_MEDIA_CHANGE
       
   928 	// Only acknowledge the media change to the PSL if we are running in normal mode
       
   929 	if(iSimulatedMediaState == EPeriphBusMediaNormal)
       
   930 		iMediaChange->AcknowledgeEvent(ETrue);
       
   931 #else
       
   932 	iMediaChange->AcknowledgeEvent(ETrue);
       
   933 #endif
       
   934 
       
   935 	// If there are multiple doors, then it is assumed that :
       
   936 	// - DMediaChangeBase::MediaState() will return EDoorClosed if ANY door is closed, and 
       
   937 	// - DPBusSocket::CardIsPresent() will return ETrue if ANY card is present
       
   938 	// so that if, for example,  one door is  open and one door closed, then the bus will 
       
   939 	// power down and then up again when one of the cards is next accessed.
       
   940 	// NB This doesn't worrk for a simulated media change since this doesn't affect the 
       
   941 	// PSL's door state
       
   942 #ifdef __ENABLE_SIMULATED_MEDIA_CHANGE
       
   943 	if ((iSimulatedMediaState == EPeriphBusMediaNormal) &&
       
   944 		(mediaState == EDoorClosed && CardIsPresent()))
       
   945 #else
       
   946 	if (mediaState == EDoorClosed && CardIsPresent())
       
   947 #endif
       
   948 		{
       
   949 		__KTRACE_OPT(KPBUS1,Kern::Printf("At least 1 door still closed"));;
       
   950 		ChangeState(EPBusOff,KErrNotReady);
       
   951 		}
       
   952 
       
   953 	}
       
   954 
       
   955 void DPBusSocket::DoorCloseEvent()
       
   956 	{
       
   957 	__KTRACE_OPT(KPBUS1,Kern::Printf(">DPBusSocket(%d)::DoorCloseEvent state %d",iSocketNumber,iState));
       
   958 
       
   959 	// NB If there are multiple doors then the bus may already be powererd up, 
       
   960 	// so it's not possible to determine the bus state.
       
   961 	//if (iState!=EPBusCardAbsent)
       
   962 	//	Panic(EDoorCloseInvalidState);
       
   963 
       
   964 	// door has been closed - check for a card
       
   965 
       
   966 	TBool cardIsPresent = CardIsPresent();
       
   967 
       
   968 #ifdef __ENABLE_SIMULATED_MEDIA_CHANGE
       
   969 	// Override the default drive state if we are simulating the media state
       
   970 	if((iSimulatedMediaState == EPeriphBusDoorOpen) || (iSimulatedMediaState == EPeriphBusMediaRemoved))
       
   971 		cardIsPresent = EFalse;
       
   972 #endif
       
   973 
       
   974 	
       
   975 	if (cardIsPresent)
       
   976 		{
       
   977 		if (iState == EPBusCardAbsent)
       
   978 			{
       
   979 			// Notifies clients of a media change
       
   980 			ChangeState(EPBusOff,KErrNotReady);
       
   981 			}
       
   982 		else	// if there's already a card present (iState != EPBusCardAbsent), power the bus off and on
       
   983 			{
       
   984 			// Notify clients of a media change, cancel any outstanding requests, close media driver(s)
       
   985 			// and set the DPrimaryMediaBase's state to EClosed to force a subsequent power-up
       
   986 			ChangeState(EPBusCardAbsent,KErrNotReady);
       
   987 			ChangeState(EPBusOff,KErrNotReady);
       
   988 			// NB Don't power down the socket when iState == EPBusCardAbsent as this can take a small amount of time 
       
   989 			// and will cause DPBusPrimaryMedia::QuickCheckStatus() to return KErrNotReady in the meantime: this will 
       
   990 			// result in any requests to the DPrimaryMediaBase being completed IMMEDIATELY with KErrNotReady, i.e. the
       
   991 			// requests won't be queued until the power up completes.
       
   992 			ResetSocket(ETrue);
       
   993 			}
       
   994 		}
       
   995 
       
   996 #ifdef __ENABLE_SIMULATED_MEDIA_CHANGE
       
   997 	// Only acknowledge the media change to the PSL if we are running in normal mode
       
   998 	if(iSimulatedMediaState == EPeriphBusMediaNormal)
       
   999 		iMediaChange->AcknowledgeEvent(EFalse);
       
  1000 #else
       
  1001 	iMediaChange->AcknowledgeEvent(EFalse);
       
  1002 #endif
       
  1003 	}
       
  1004 	/**
       
  1005 	Gets pointer to the PBus Socket corresponding to the opened logical unit.
       
  1006 	@param anId	logical id of the PBus Socket.	
       
  1007 	@return Pointer to the PBusSocket for valid anId, else NULL.
       
  1008 	*/
       
  1009 EXPORT_C DPBusSocket* DPBusSocket::SocketFromId(TInt anId)
       
  1010 	{
       
  1011 	if (anId>=0 && anId<KMaxPBusSockets)
       
  1012 		return TheSockets[anId];
       
  1013 	return NULL;
       
  1014 	}
       
  1015 
       
  1016 	/**
       
  1017 	Default implementation for handling debug functionality.
       
  1018 	This function can only be used if __ENABLE_SIMULATED_MEDIA_CHANGE is defined. 
       
  1019 	Otherwise, this method is not implemented and it always returns KErrNotSupported.
       
  1020 
       
  1021 	@param aFunction	refer to TPBusDebugFunction
       
  1022 	@param aParam1	Simulated media state.
       
  1023 	@param aParam2 Not used in this method.
       
  1024 	@return  KErrNone - if successful, otherwise one of the other system-wide error 
       
  1025 	codes including: 
       
  1026 			KErrNotSupported - if aFunction is invalid or __ENABLE_SIMULATED_MEDIA_CHANGE 
       
  1027 	is not defined,
       
  1028 			KErrArgument -  if aParam1 does not corresponds to TPBusSimulateMediaState.
       
  1029 	@see TPBusSimulateMediaState
       
  1030 	@see TPBusDebugFunction
       
  1031 	*/
       
  1032 EXPORT_C TInt DPBusSocket::ControlIO(TInt aFunction, TAny* aParam1, TAny* /*aParam2*/)
       
  1033 	{
       
  1034 	TInt err = KErrNone;
       
  1035 
       
  1036 	switch(aFunction)
       
  1037 		{
       
  1038 		case EControlMediaState:
       
  1039 			//
       
  1040 			// EOverrideMediaState - Set the media state manually for simulation purposes.
       
  1041 			//	- aParam1 : Simulated Media State (TPBusSimulateMediaState)
       
  1042 			//
       
  1043 			{
       
  1044 #ifdef __ENABLE_SIMULATED_MEDIA_CHANGE
       
  1045 			TUint16 newState = (TUint16)(TInt)aParam1;
       
  1046 			if(newState != iSimulatedMediaState)
       
  1047 				{
       
  1048 				iSimulatedMediaState = newState;
       
  1049 
       
  1050 				switch(iSimulatedMediaState)
       
  1051 					{
       
  1052 					case EPeriphBusMediaNormal:
       
  1053 						//
       
  1054 						// Normal state
       
  1055 						// - Signal that the door is open and generate a media change.
       
  1056 						//
       
  1057 						iMediaChange->MediaChangeEvent(ETrue);
       
  1058 						break;
       
  1059 					
       
  1060 					case EPeriphBusDoorOpen:
       
  1061 						//
       
  1062 						// Simulated door open or back to normal state.
       
  1063 						// - Signal that the door is open and generate a media change.
       
  1064 						//
       
  1065 						MediaChangeEvent(ETrue);
       
  1066 						break;
       
  1067 					
       
  1068 					case EPeriphBusMediaRemoved:
       
  1069 					case EPeriphBusMediaPresent:
       
  1070 						//
       
  1071 						// Simulated door close with media present or absent
       
  1072 						// - Signal that the door is closed.
       
  1073 						//
       
  1074 						MediaChangeEvent(EFalse);
       
  1075 						break;
       
  1076 
       
  1077 					case EPeriphBusMediaDoubleDoorOpen:
       
  1078 						// simulate 2 door open interrupts 
       
  1079 						iSimulatedMediaState = EPeriphBusMediaNormal;
       
  1080 						iMediaChange->MediaChangeEvent(ETrue);
       
  1081 						iMediaChange->MediaChangeEvent(ETrue);
       
  1082 						break;
       
  1083 
       
  1084 					default:
       
  1085 						//
       
  1086 						// Unsupported media state
       
  1087 						//
       
  1088 						err = KErrArgument;
       
  1089 						break;
       
  1090 					}
       
  1091 				}
       
  1092 #else
       
  1093 			aParam1 = aParam1;
       
  1094 			err = KErrNotSupported;
       
  1095 #endif
       
  1096 			break;
       
  1097 			}
       
  1098 
       
  1099 		default:
       
  1100 			err = KErrNotSupported;
       
  1101 			break;
       
  1102 		}
       
  1103 
       
  1104 	return err;
       
  1105 	}
       
  1106 
       
  1107 /********************************************
       
  1108  * Extension entry point
       
  1109  ********************************************/
       
  1110 
       
  1111 GLDEF_C TInt KernelModuleEntry(TInt aReason)
       
  1112 	{
       
  1113 	if (aReason==KModuleEntryReasonExtensionInit0 || aReason==KModuleEntryReasonExtensionInit1)
       
  1114 		return KErrNone;
       
  1115 	return KErrArgument;
       
  1116 	}
       
  1117 
       
  1118 
       
  1119 
       
  1120 
       
  1121