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