os/boardsupport/emulator/emulatorbsp/specific/sdcard/sdcard4c/pp_cprm.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
// Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
//
sl@0
    15
sl@0
    16
#include "plat_priv.h"
sl@0
    17
#include <property.h>
sl@0
    18
#include <variant.h>
sl@0
    19
#include "pp_cprm.h" 
sl@0
    20
sl@0
    21
const TInt  KDiskSectorSize=512;
sl@0
    22
sl@0
    23
const TInt KTotalMDiskSize=0x100000; // 1MB (if changing this then also change CSD response)
sl@0
    24
sl@0
    25
// ======== error code conversion ========
sl@0
    26
sl@0
    27
GLDEF_C TInt MapLastErrorEpoc()
sl@0
    28
//
sl@0
    29
// map an Win32 error code to Epoc32 value
sl@0
    30
//
sl@0
    31
	{
sl@0
    32
	TInt res=KErrGeneral;
sl@0
    33
	switch (GetLastError())
sl@0
    34
		{
sl@0
    35
		case ERROR_SHARING_VIOLATION : res=KErrAccessDenied; break;
sl@0
    36
		case ERROR_LOCK_VIOLATION : res=KErrLocked; break;
sl@0
    37
		case ERROR_FILE_NOT_FOUND: res=KErrNotFound; break;
sl@0
    38
		case ERROR_PATH_NOT_FOUND: res=KErrPathNotFound; break;
sl@0
    39
		case ERROR_ALREADY_EXISTS:
sl@0
    40
		case ERROR_FILE_EXISTS:
sl@0
    41
			res=KErrAlreadyExists;
sl@0
    42
			break;
sl@0
    43
		case ERROR_NOT_READY: res=KErrNotReady; break;
sl@0
    44
		case ERROR_UNRECOGNIZED_VOLUME:
sl@0
    45
		case ERROR_NOT_DOS_DISK:
sl@0
    46
			res=KErrUnknown;
sl@0
    47
			break;
sl@0
    48
		case ERROR_UNRECOGNIZED_MEDIA: res=KErrCorrupt; break;
sl@0
    49
		case ERROR_INVALID_NAME: res=KErrBadName; break;
sl@0
    50
		case ERROR_NO_MORE_FILES: res=KErrEof; break;
sl@0
    51
		}
sl@0
    52
	return(res);
sl@0
    53
	}
sl@0
    54
sl@0
    55
GLDEF_C TMMCErr MapLastErrorMmc()
sl@0
    56
//
sl@0
    57
// map Win32 error to a TMMCErr error.
sl@0
    58
//
sl@0
    59
	{
sl@0
    60
	DWORD r=GetLastError();
sl@0
    61
	TInt res=KErrGeneral;
sl@0
    62
	switch (r)
sl@0
    63
		{
sl@0
    64
		case ERROR_SHARING_VIOLATION:
sl@0
    65
		case ERROR_LOCK_VIOLATION:
sl@0
    66
			res=KMMCErrLocked;			// KErrLocked
sl@0
    67
			break;
sl@0
    68
		case ERROR_FILE_NOT_FOUND:
sl@0
    69
		case ERROR_PATH_NOT_FOUND:
sl@0
    70
			res=KMMCErrNotFound;		// KErrNotFound
sl@0
    71
			break;
sl@0
    72
		case ERROR_ALREADY_EXISTS:
sl@0
    73
		case ERROR_FILE_EXISTS:
sl@0
    74
			res=KMMCErrAlreadyExists;	// KErrAlreadyExists
sl@0
    75
			break;
sl@0
    76
		case ERROR_NOT_READY: res=KMMCErrNoCard; break;
sl@0
    77
		case ERROR_UNRECOGNIZED_VOLUME:
sl@0
    78
		case ERROR_NOT_DOS_DISK:
sl@0
    79
			res=KMMCErrGeneral;			// KErrGeneral
sl@0
    80
			break;
sl@0
    81
		case ERROR_UNRECOGNIZED_MEDIA:
sl@0
    82
		case ERROR_INVALID_NAME:
sl@0
    83
		case ERROR_NO_MORE_FILES:
sl@0
    84
			res=KMMCErrResponseCRC; 	// KErrCorrupt
sl@0
    85
			break;
sl@0
    86
		}
sl@0
    87
	return(res);
sl@0
    88
	}
sl@0
    89
sl@0
    90
// ======== DWinsCPRMStack ========
sl@0
    91
sl@0
    92
DWinsCPRMStack::DWinsCPRMStack(TInt aBus, DMMCSocket* aSocket)
sl@0
    93
: DCPRMStack(aBus, aSocket)
sl@0
    94
	{	
sl@0
    95
	iAddressedCard=KBroadcastToAllCards;
sl@0
    96
//	iCMD42Failed=EFalse;
sl@0
    97
	}
sl@0
    98
sl@0
    99
sl@0
   100
TInt DWinsCPRMStack::Init()
sl@0
   101
//
sl@0
   102
// Allocate any resources. Only created once on kernel initialization so dont
sl@0
   103
// worry about cleanup if it leaves.
sl@0
   104
//
sl@0
   105
	{
sl@0
   106
	if((iCardArray = new TSDCardArray(this)) == NULL)
sl@0
   107
		return KErrNoMemory;
sl@0
   108
sl@0
   109
	TInt r=DCPRMStack::Init();
sl@0
   110
	if(r!=KErrNone)
sl@0
   111
		return r;
sl@0
   112
sl@0
   113
	DMediaChangeBase* pMCBase = MMCSocket()->iMediaChange;
sl@0
   114
	static_cast<DWinsMMCMediaChange*>(pMCBase)->SetStackP(this);
sl@0
   115
	Wins::SetMediaChangeCallBackPtr(DWinsMMCMediaChange::MediaChangeCallBack, (TAny*)pMCBase);
sl@0
   116
sl@0
   117
	//
sl@0
   118
	// Over time memory can become fragmented, and so it is not possible to
sl@0
   119
	// allocate physically contiguous pages.  Therefore, the buffers for IO
sl@0
   120
	// are allocated at startup.
sl@0
   121
	//
sl@0
   122
	// block and erase sector size characteristics depend on the specific
sl@0
   123
	// card model, and so the initial values are estimates based on a typical
sl@0
   124
	// card.  If these do not match the actual card's block size (or erase
sl@0
   125
	// size, for SD,) then the media driver just gets a reduced or increased
sl@0
   126
	// buffer area, and its efficiency varies accordingly.
sl@0
   127
	//
sl@0
   128
	// For the WINS implementation, fragmentation does not matter because
sl@0
   129
	// DMA is not used.  The memory must still be allocated here so MEDMMC is
sl@0
   130
	// able to use it.
sl@0
   131
	//
sl@0
   132
	// The constant calculations could be folded, but this illustrates how the
sl@0
   133
	// values are derived.
sl@0
   134
	//
sl@0
   135
sl@0
   136
	// MMC - values from Hitachi 16Mb card, datasheet HB288016MM1
sl@0
   137
sl@0
   138
	// minor buffer must contain enough space for MBR or block
sl@0
   139
	const TUint mmcBlkSzLog2 = 9;				// READ_BLK_LEN and WRITE_BLK_LEN
sl@0
   140
	const TUint mmcBlkSz = 1 << mmcBlkSzLog2;
sl@0
   141
	const TInt mmcMinorBufLen = Max(KDiskSectorSize, mmcBlkSz);
sl@0
   142
sl@0
   143
	const TInt KMinMMCBlocksInBuffer = 8;
sl@0
   144
	const TInt mmcCchBufLen = KMinMMCBlocksInBuffer << mmcBlkSzLog2;
sl@0
   145
sl@0
   146
	const TInt mmcTotalBufLen = mmcMinorBufLen + mmcCchBufLen;
sl@0
   147
sl@0
   148
	// SDCard - values from 64Mb Panasonic RP-SD064
sl@0
   149
sl@0
   150
	const TUint sdBlkSzLog2 = 9;				// READ_BL_LEN and WRITE_BLK_LEN
sl@0
   151
	const TUint sdBlkSz = 1 << sdBlkSzLog2;
sl@0
   152
	const TInt sdMinorBufLen = Max(KDiskSectorSize, sdBlkSz);
sl@0
   153
sl@0
   154
	const TUint ss = 0x1f;						// SECTOR_SIZE, add 1 for sector count
sl@0
   155
	const TInt KMinSDBlocksInBuffer = 8;
sl@0
   156
	const TInt sdCchBufLen = Max(KMinSDBlocksInBuffer, ss + 1) << sdBlkSzLog2;
sl@0
   157
sl@0
   158
	const TInt sdTotalBufLen = sdMinorBufLen + sdCchBufLen;
sl@0
   159
sl@0
   160
	const TInt totalBufLen = Max(mmcTotalBufLen, sdTotalBufLen);
sl@0
   161
sl@0
   162
	iMDBuf = reinterpret_cast<TUint8*>(Kern::Alloc(totalBufLen));
sl@0
   163
	iMDBufLen = totalBufLen;
sl@0
   164
sl@0
   165
	// initialize each card on the stack
sl@0
   166
	TInt i;
sl@0
   167
	for (i = 0; i < KTotalWinsCards; ++i)
sl@0
   168
		{
sl@0
   169
		TInt r = SetupSimulatedCard(i);
sl@0
   170
		if (r != KErrNone)
sl@0
   171
			return r;
sl@0
   172
		}
sl@0
   173
sl@0
   174
	// initialize pointers to currently present cards
sl@0
   175
sl@0
   176
	// Slot zero can toggle between no card; card 0 and card 1.  The current state is
sl@0
   177
	// determined by *Wins::CurrentPBusDevicePtr() and toggled by pressing F4 when F5
sl@0
   178
	// (door open) is held down.  Because this function is only executed at startup,
sl@0
   179
	// assume start with card zero.
sl@0
   180
	iCardInfo[0] = iCardPool[0];
sl@0
   181
	for (i = 1; i < KTotalWinsCardSlots; ++i)
sl@0
   182
		{
sl@0
   183
		iCardInfo[i]=iCardPool[i+1];
sl@0
   184
		}
sl@0
   185
sl@0
   186
	return KErrNone;
sl@0
   187
	}
sl@0
   188
sl@0
   189
void DWinsCPRMStack::MachineInfo(TMMCMachineInfo& aMachineInfo)
sl@0
   190
	{
sl@0
   191
	aMachineInfo.iTotalSockets=KTotalWinsCardSlots;
sl@0
   192
	aMachineInfo.iTotalMediaChanges=0;  		// Not used at present
sl@0
   193
	aMachineInfo.iTotalPrimarySupplies=0;		// Not used at present
sl@0
   194
sl@0
   195
	aMachineInfo.iSPIMode=EFalse;
sl@0
   196
    aMachineInfo.iBaseBusNumber=0;
sl@0
   197
sl@0
   198
	__ASSERT_DEBUG(aMachineInfo.iTotalSockets<=KMaxMMCardsPerStack,
sl@0
   199
					DWinsCPRMStack::Panic(DWinsCPRMStack::EWinsMMCBadMachineInfo));
sl@0
   200
	}
sl@0
   201
sl@0
   202
void DWinsCPRMStack::AdjustPartialRead(
sl@0
   203
#ifdef _DEBUG
sl@0
   204
	const TMMCard* aCard,
sl@0
   205
#else
sl@0
   206
	const TMMCard* /*aCard*/,
sl@0
   207
#endif
sl@0
   208
	TUint32 aStart, TUint32 aEnd, TUint32* aPhysStart, TUint32* aPhysEnd) const
sl@0
   209
	{
sl@0
   210
#ifdef _DEBUG
sl@0
   211
	const TUint32 blkLen = aCard->CSD().ReadBlockLength();
sl@0
   212
	const TUint32 blkMsk = blkLen - 1;
sl@0
   213
sl@0
   214
	__ASSERT_DEBUG(aCard->CSD().ReadBlPartial(), Panic(EWinsMMCAPRNotSupp));
sl@0
   215
	__ASSERT_DEBUG(aEnd - aStart <= blkLen, Panic(EWinsMMCAPRRange));
sl@0
   216
	__ASSERT_DEBUG((aEnd & ~blkMsk) > (aStart & ~blkMsk), Panic(EWinsMMCAPRBoundary));
sl@0
   217
#endif
sl@0
   218
sl@0
   219
	*aPhysStart = aStart & ~0x3;
sl@0
   220
	*aPhysEnd = (aEnd + 0x3) & ~0x3;
sl@0
   221
	}
sl@0
   222
sl@0
   223
void DWinsCPRMStack::GetBufferInfo(TUint8** aMDBuf, TInt* aMDBufLen)
sl@0
   224
	{
sl@0
   225
	*aMDBuf = iMDBuf;
sl@0
   226
	*aMDBufLen = iMDBufLen;
sl@0
   227
	}
sl@0
   228
sl@0
   229
void DWinsCPRMStack::Panic(TWinsMMCPanic aPanic)
sl@0
   230
	{
sl@0
   231
	_LIT(KPncNm,"PBUS-MMCSD-WINS");
sl@0
   232
	Kern::PanicCurrentThread(KPncNm,aPanic);
sl@0
   233
	}
sl@0
   234
sl@0
   235
TInt DWinsCPRMStack::SetupSimulatedCard(TInt aCardNum)
sl@0
   236
//
sl@0
   237
// allocate individual card with Win32 file.  Only called at bootup, so no cleanup if fails.
sl@0
   238
//
sl@0
   239
	{
sl@0
   240
	TWinsCardInfo* cip = new TWinsCardInfo;
sl@0
   241
	if (cip == 0)
sl@0
   242
		return KErrNoMemory;
sl@0
   243
sl@0
   244
	TUint8 cid[KMMCCIDLength];
sl@0
   245
	cid[0] = 'C';
sl@0
   246
	cid[1] = 'I';
sl@0
   247
	cid[2] = 'D';
sl@0
   248
	cid[3] = TUint8('0' + aCardNum);
sl@0
   249
	TInt j;
sl@0
   250
	for (j = 4; j < KMMCCIDLength - 1; ++j)
sl@0
   251
		cid[j] = 'c';
sl@0
   252
	cid[KMMCCIDLength - 1] = '#';				// '#' = 0x23, bit zero must be 1
sl@0
   253
	cip->iCID=cid;
sl@0
   254
sl@0
   255
	cip->iPWD = new TMediaPassword;
sl@0
   256
	if (! cip->iPWD)
sl@0
   257
		{
sl@0
   258
		delete cip;
sl@0
   259
		return KErrNoMemory;
sl@0
   260
		}
sl@0
   261
sl@0
   262
	// cards in slot zero are SD
sl@0
   263
	TInt mediaAreas;
sl@0
   264
	if (aCardNum <= 1)
sl@0
   265
		{
sl@0
   266
		cip->iIsSDCard = ETrue;
sl@0
   267
		mediaAreas = 2;
sl@0
   268
		}
sl@0
   269
	else
sl@0
   270
		{
sl@0
   271
		cip->iIsSDCard = EFalse;
sl@0
   272
		mediaAreas = 1;
sl@0
   273
		}
sl@0
   274
sl@0
   275
	cip->iState=ECardStateIdle;
sl@0
   276
sl@0
   277
	for (TInt area = 0; area < mediaAreas; ++area)
sl@0
   278
		{
sl@0
   279
		TInt r = CreateBinFileForCard(aCardNum, area, &cip->iAreaHandles[area]);
sl@0
   280
		if (r != KErrNone)
sl@0
   281
			return r;
sl@0
   282
		}
sl@0
   283
	iCardPool[aCardNum]=cip;
sl@0
   284
	return(KErrNone);
sl@0
   285
	}
sl@0
   286
sl@0
   287
TInt DWinsCPRMStack::CreateBinFileForCard(TInt aCardNum, TInt aAreaNum, HANDLE* aHandle)
sl@0
   288
//
sl@0
   289
// create .bin file in temp directory to contain media area of card.
sl@0
   290
//
sl@0
   291
	{
sl@0
   292
	const char* emulatorPath = Property::GetString("EmulatorMediaPath");
sl@0
   293
	if (!Emulator::CreateAllDirectories(emulatorPath))
sl@0
   294
		return Emulator::LastError();
sl@0
   295
sl@0
   296
	TBuf8<KMaxFileName> fn8(_L8(emulatorPath));
sl@0
   297
	fn8.Append(_L8("MMCCRD"));
sl@0
   298
	fn8.AppendNum(aCardNum);
sl@0
   299
	fn8.Append('A'+aAreaNum);
sl@0
   300
	fn8.Append(_L8(".BIN"));
sl@0
   301
	fn8.Append('\0');
sl@0
   302
sl@0
   303
	*aHandle = CreateFileA(
sl@0
   304
		(LPCSTR) fn8.Ptr(),					// LPCSTR lpFileName,
sl@0
   305
		GENERIC_READ | GENERIC_WRITE,		// DWORD dwDesiredAccess
sl@0
   306
		FILE_SHARE_READ | FILE_SHARE_WRITE,	// DWORD dwShareMode
sl@0
   307
		NULL,								// LPSECURITY_ATTRIBUTES lpSecurityAttributes
sl@0
   308
		OPEN_ALWAYS,						// DWORD dwCreationDisposition
sl@0
   309
		FILE_FLAG_RANDOM_ACCESS,			// DWORD dwFlagsAndAttributes
sl@0
   310
		NULL);								// HANDLE hTemplateFile
sl@0
   311
sl@0
   312
	if (*aHandle == INVALID_HANDLE_VALUE)
sl@0
   313
	    return MapLastErrorEpoc();
sl@0
   314
	
sl@0
   315
	if (	SetFilePointer(*aHandle, KTotalMDiskSize, NULL, FILE_BEGIN) == 0xffffffffu
sl@0
   316
		||	! SetEndOfFile(*aHandle) )
sl@0
   317
		{
sl@0
   318
		CloseHandle(*aHandle);
sl@0
   319
	    return MapLastErrorEpoc();
sl@0
   320
		}
sl@0
   321
sl@0
   322
	return KErrNone;
sl@0
   323
	}
sl@0
   324
sl@0
   325
void DWinsCPRMStack::SetBusConfigDefaults(TMMCBusConfig& aConfig, TUint aClock)
sl@0
   326
	{
sl@0
   327
	const TUint KWinsMaxHwInterfaceClk=104000;
sl@0
   328
	const TUint KWinsResponseTimeOut=6400;
sl@0
   329
	const TUint KWinsDataTimeOut=40000;
sl@0
   330
	const TUint KWinsBusyTimeOut=200000;
sl@0
   331
sl@0
   332
	aConfig.iBusClock = (aClock > KWinsMaxHwInterfaceClk) ? KWinsMaxHwInterfaceClk : aClock;
sl@0
   333
	aConfig.iResponseTimeOut=KWinsResponseTimeOut;
sl@0
   334
	aConfig.iDataTimeOut=KWinsDataTimeOut;
sl@0
   335
	aConfig.iBusyTimeOut=KWinsBusyTimeOut;
sl@0
   336
	}
sl@0
   337
sl@0
   338
void DWinsCPRMStack::InitClockOff()
sl@0
   339
	{
sl@0
   340
	// empty.
sl@0
   341
	}
sl@0
   342
sl@0
   343
void DWinsCPRMStack::ASSPReset()
sl@0
   344
	{
sl@0
   345
	// empty.
sl@0
   346
	}
sl@0
   347
sl@0
   348
void DWinsCPRMStack::ASSPDisengage()
sl@0
   349
	{
sl@0
   350
	// empty.
sl@0
   351
	}
sl@0
   352
sl@0
   353
void DWinsCPRMStack::DoPowerDown()
sl@0
   354
	{
sl@0
   355
	// empty.
sl@0
   356
	}
sl@0
   357
sl@0
   358
LOCAL_C TInt SetMediaPasswordEnvironmentVar(TInt aSocketNum,TInt aCardNum,const TDesC8& aPasswd)
sl@0
   359
// 
sl@0
   360
// Set the password for local drive 'aLocalDrive', card number 'aCardNum' to 'aPasswd' - as an
sl@0
   361
// environment variable. Note that the card number is only relevant where the emulated drive
sl@0
   362
// supports card hot-swapping (i.e. F4 whilst F5 is held down).
sl@0
   363
//
sl@0
   364
	{
sl@0
   365
	// Setup the appropriate environment variable string '_EPOC_LocDrv_<locDrvNum>_PWORD_<cardNum>'
sl@0
   366
	TUint16 envVar[]=L"_EPOC_Socket_X_PWORD_Y";
sl@0
   367
sl@0
   368
	envVar[13]=(TUint16)('0'+aSocketNum);
sl@0
   369
	envVar[21]=(TUint16)('0'+aCardNum);
sl@0
   370
	
sl@0
   371
	// Setup the new value of the environment variable
sl@0
   372
	TUint16	envVal[100];
sl@0
   373
	TInt len=aPasswd.Length();
sl@0
   374
sl@0
   375
	// the password may be empty if a card's password is cleared
sl@0
   376
	if (len>(100-1))
sl@0
   377
		return(KErrArgument);
sl@0
   378
	memcpy(&envVal[0],reinterpret_cast<const TUint16 *>(aPasswd.Ptr()),len);
sl@0
   379
	envVal[len>>1]='\0';
sl@0
   380
sl@0
   381
	// Now set the new value for the environment variable
sl@0
   382
	if (SetEnvironmentVariable(envVar,&envVal[0]))
sl@0
   383
		return(KErrNone);
sl@0
   384
sl@0
   385
	return KErrGeneral;
sl@0
   386
	}
sl@0
   387
sl@0
   388
LOCAL_C TInt MediaPasswordEnvironmentVar(TInt aSocketNum,TInt aCardNum,TDes8& aPasswd)
sl@0
   389
// 
sl@0
   390
// Get the password for local drive 'aLocalDrive', card number 'aCardNum' into 'aPasswd' - from
sl@0
   391
// an environment variable. Note that the card number is only relevant where the emulated drive
sl@0
   392
// supports card hot-swapping (i.e. F4 whilst F5 is held down).
sl@0
   393
//
sl@0
   394
	{
sl@0
   395
	TUint16 envVar[]=L"_EPOC_Socket_X_PWORD_Y";
sl@0
   396
sl@0
   397
	envVar[13]=(TUint16)('0'+aSocketNum);
sl@0
   398
	envVar[21]=(TUint16)('0'+aCardNum);
sl@0
   399
	
sl@0
   400
	TUint16 envVal[100];	// To hold the value of the retreived environment variable
sl@0
   401
	
sl@0
   402
	DWORD len=GetEnvironmentVariable(envVar,&envVal[0],100);
sl@0
   403
	if (len>(TUint)100)
sl@0
   404
		return(KErrGeneral);
sl@0
   405
	if (len)
sl@0
   406
		{
sl@0
   407
		// Found the requested environment variable so there is a password for this local drive / card. 
sl@0
   408
		if ((len<<1)<=KMaxMediaPassword)
sl@0
   409
			{
sl@0
   410
			aPasswd.FillZ(KMaxMediaPassword);
sl@0
   411
			aPasswd.Zero();
sl@0
   412
			aPasswd.Copy(reinterpret_cast<TUint8*>(&envVal[0]),len<<1);
sl@0
   413
			return(KErrNone);	
sl@0
   414
			}
sl@0
   415
		else	
sl@0
   416
			return(KErrGeneral);	
sl@0
   417
		}
sl@0
   418
sl@0
   419
	return(KErrNotFound);
sl@0
   420
	}
sl@0
   421
sl@0
   422
TMMCErr DWinsCPRMStack::DoPowerUpSM()
sl@0
   423
	{
sl@0
   424
	enum states
sl@0
   425
		{
sl@0
   426
		EStBegin=0,
sl@0
   427
		EStEnd
sl@0
   428
		};
sl@0
   429
sl@0
   430
	SMF_BEGIN
sl@0
   431
sl@0
   432
		if(MMCSocket()->iVcc->SetState(EPsuOnCurLimit) != KErrNone)
sl@0
   433
			return KMMCErrHardware;
sl@0
   434
sl@0
   435
		for (TInt i = 0; i < KTotalWinsCardSlots; ++i)
sl@0
   436
			{
sl@0
   437
			// if card has a password, it will be locked on power up
sl@0
   438
			TInt cardNum = (i==0) ? *Wins::CurrentPBusDevicePtr() : i + 1;
sl@0
   439
			if (	cardNum >= 0
sl@0
   440
				&&	MediaPasswordEnvironmentVar(
sl@0
   441
						MMCSocket()->iSocketNumber, cardNum, *(iCardInfo[i]->iPWD))
sl@0
   442
					==	KErrNone)
sl@0
   443
				{
sl@0
   444
				iCardInfo[i]->iIsLocked = (iCardInfo[i]->iPWD->Length() > 0);
sl@0
   445
				}
sl@0
   446
			else	
sl@0
   447
				iCardInfo[i]->iIsLocked=EFalse;
sl@0
   448
sl@0
   449
			iCardInfo[i]->iState = ECardStateIdle;
sl@0
   450
			iCardInfo[i]->iRCA=0x0001;		// Default RCA - spec 2.2, s4.2.1, 5.4
sl@0
   451
			}
sl@0
   452
sl@0
   453
		ReportPowerUp();
sl@0
   454
sl@0
   455
	SMF_END
sl@0
   456
	}
sl@0
   457
sl@0
   458
TMMCErr DWinsCPRMStack::InitClockOnSM()
sl@0
   459
	{
sl@0
   460
	enum states
sl@0
   461
		{
sl@0
   462
		EStBegin=0,
sl@0
   463
		EStEnd
sl@0
   464
		};
sl@0
   465
	SMF_BEGIN
sl@0
   466
sl@0
   467
	SMF_END
sl@0
   468
	}
sl@0
   469
sl@0
   470
void DWinsCPRMStack::AddressCard(TInt aCardNumber)
sl@0
   471
	{
sl@0
   472
	iAddressedCard = aCardNumber;
sl@0
   473
	}
sl@0
   474
sl@0
   475
sl@0
   476
TInt DWinsCPRMStack::GetTargetSlotNumber(const TRCA& anRCA)
sl@0
   477
//
sl@0
   478
// when the controller is given a command with an embedded RCA, this function
sl@0
   479
// works out which physical card slot it corresponds to.  If no card has been
sl@0
   480
// assigned the RCA then it returns -1.
sl@0
   481
//
sl@0
   482
	{
sl@0
   483
	TInt targetIdx = -1;
sl@0
   484
sl@0
   485
	for (TInt i = 0; i < KTotalWinsCardSlots; ++i)
sl@0
   486
		{
sl@0
   487
		if (iCardInfo[i]->iRCA==anRCA)
sl@0
   488
			{
sl@0
   489
			targetIdx=i;
sl@0
   490
			break;
sl@0
   491
			}
sl@0
   492
		}
sl@0
   493
sl@0
   494
	return(targetIdx);
sl@0
   495
	}
sl@0
   496
sl@0
   497
TMMCErr DWinsCPRMStack::IssueMMCCommandSM()
sl@0
   498
	{
sl@0
   499
	enum states
sl@0
   500
		{
sl@0
   501
		EStBegin=0,
sl@0
   502
		EStEnd
sl@0
   503
		};
sl@0
   504
sl@0
   505
	TMMCCommandDesc& cmd = Command();
sl@0
   506
sl@0
   507
	// If the command contains an embedded RCA then extract it	
sl@0
   508
	TRCA tgtRCA=0;
sl@0
   509
	TBool supRCA=EFalse;
sl@0
   510
	if (/*cmd.iCommand == ECmdSetRelativeAddr	||	*/cmd.iCommand == ECmdSelectCard
sl@0
   511
	||	cmd.iCommand == ECmdSendCSD			||	cmd.iCommand == ECmdSendCID
sl@0
   512
	||	cmd.iCommand == ECmdSendStatus		||	cmd.iCommand == ECmdGoInactiveState
sl@0
   513
	||	cmd.iCommand == ECmdFastIO 			||  cmd.iCommand == ECmdAppCmd )
sl@0
   514
		{
sl@0
   515
		if ((cmd.iArgument >> 16) != 0)
sl@0
   516
			{
sl@0
   517
			supRCA=ETrue;
sl@0
   518
			tgtRCA=TUint16(cmd.iArgument >> 16);
sl@0
   519
			}
sl@0
   520
		}
sl@0
   521
sl@0
   522
	// if the card contains an embedded RCA, work out which slot it corresponds to.
sl@0
   523
	// At the end of the function, this card is used to generate the R1 response.
sl@0
   524
	// Assume that if rca is supplied it either corresponds to the selected card or
sl@0
   525
	// broadcast mode is on.  (An exception is CMD7 with arg0 to deselect all cards.)
sl@0
   526
sl@0
   527
	TInt targetCard = supRCA ? GetTargetSlotNumber(tgtRCA) : iAddressedCard;
sl@0
   528
	TBool rto = EFalse;							// response timeout
sl@0
   529
sl@0
   530
	// if try to access card zero has been set to holding no card via F5 / F4 then timeout.
sl@0
   531
	if ((targetCard == 0) && *Wins::CurrentPBusDevicePtr() < 0)
sl@0
   532
		return KMMCErrResponseTimeOut;
sl@0
   533
	
sl@0
   534
	HANDLE winHandle;
sl@0
   535
sl@0
   536
	// CMD42 is a data transfer command.  That means the R1 response that it returns
sl@0
   537
	// immediately is the state it is in on receiving the data block, and not after
sl@0
   538
	// processing it.  If the data block is invalid then LOCK_UNLOCK_FAILED will be
sl@0
   539
	// set in the R1 response which is sent in reply to the next command.
sl@0
   540
sl@0
   541
	TBool nextCMD42Failed = EFalse;
sl@0
   542
	TBool lock_unlock_failed=EFalse;
sl@0
   543
sl@0
   544
	// When the card is locked, it will only respond to basic command class (0) and
sl@0
   545
	// lock card command class (7).  An exception is CMD16.  This is sent before CMD42,
sl@0
   546
	// but is classified (MMC Spec 23.2, table 5) as belonging to classes 2 and 4.
sl@0
   547
	// For data transfer commands, LOCK_UNLOCK_FAIL is set in response to the following
sl@0
   548
sl@0
   549
	TMMCCommandEnum origCmd = cmd.iCommand;
sl@0
   550
sl@0
   551
	// if targetting locked card...
sl@0
   552
	if (targetCard != KBroadcastToAllCards && iCardInfo[targetCard]->iIsLocked)
sl@0
   553
		{
sl@0
   554
		// ...and not command used in init or CMD42 sequence...
sl@0
   555
		if (!(	((cmd.iSpec.iCommandClass & (KMMCCmdClassApplication | KMMCCmdClassBasic | KMMCCmdClassLockCard)) != 0)
sl@0
   556
			||	(cmd.iCommand == ECmdSetBlockLen) || (cmd.iCommand == ECmdAppCmd) ))
sl@0
   557
			{
sl@0
   558
			lock_unlock_failed = ETrue;
sl@0
   559
			cmd.iCommand = (TMMCCommandEnum) -1;	// skip case processing
sl@0
   560
			}
sl@0
   561
		}
sl@0
   562
sl@0
   563
	SMF_BEGIN
sl@0
   564
sl@0
   565
	switch (cmd.iCommand)
sl@0
   566
		{
sl@0
   567
		case ECmdGoIdleState:	// CMD0
sl@0
   568
			if (iAddressedCard != KBroadcastToAllCards)
sl@0
   569
				iCardInfo[iAddressedCard]->iState = ECardStateIdle;
sl@0
   570
			else
sl@0
   571
				{
sl@0
   572
				for (TInt i = 0; i < KTotalWinsCardSlots; ++i)
sl@0
   573
					iCardInfo[i]->iState = ECardStateIdle;
sl@0
   574
				}
sl@0
   575
			break;
sl@0
   576
sl@0
   577
		case ECmd41:
sl@0
   578
		case ECmdSendOpCond:	// CMD1
sl@0
   579
			{
sl@0
   580
			if (iAddressedCard != KBroadcastToAllCards)
sl@0
   581
				iCardInfo[iAddressedCard]->iState = ECardStateReady;
sl@0
   582
			else
sl@0
   583
				{
sl@0
   584
				for (TInt i = 0; i < KTotalWinsCardSlots; ++i)
sl@0
   585
					iCardInfo[i]->iState = ECardStateReady;
sl@0
   586
				}
sl@0
   587
sl@0
   588
			// bit31 is set to indicate cards are not still powering up
sl@0
   589
			TUint32 r3 = KMMCWinsCardOCRValue | KMMCOCRBusy;
sl@0
   590
			TMMC::BigEndian4Bytes(cmd.iResponse, r3);
sl@0
   591
			}
sl@0
   592
			break;
sl@0
   593
sl@0
   594
		case ECmdAllSendCID:	// CMD2
sl@0
   595
			{
sl@0
   596
			TInt idx;
sl@0
   597
			if (iAddressedCard != KBroadcastToAllCards)
sl@0
   598
				{
sl@0
   599
				idx = iAddressedCard;
sl@0
   600
				__ASSERT_DEBUG(
sl@0
   601
					iCardInfo[iAddressedCard]->iState == ECardStateReady,
sl@0
   602
					DWinsCPRMStack::Panic(DWinsCPRMStack::EStkIMCBadStateCmd2));
sl@0
   603
				}
sl@0
   604
			else
sl@0
   605
				idx = FindAnyCardInStack(ECardStateReady);
sl@0
   606
sl@0
   607
			if (idx == -1)
sl@0
   608
				rto = ETrue;
sl@0
   609
			else
sl@0
   610
				{
sl@0
   611
				iCardInfo[idx]->iCID.Copy(cmd.iResponse);
sl@0
   612
				iCardInfo[idx]->iState = ECardStateIdent;
sl@0
   613
				}
sl@0
   614
			}
sl@0
   615
			break;
sl@0
   616
sl@0
   617
		case ECmdSetRelativeAddr:	// CMD3
sl@0
   618
			{
sl@0
   619
			TInt idx;
sl@0
   620
			if (iAddressedCard != KBroadcastToAllCards)
sl@0
   621
				{
sl@0
   622
				__ASSERT_DEBUG(
sl@0
   623
					iCardInfo[iAddressedCard]->iState == ECardStateIdent,
sl@0
   624
					DWinsCPRMStack::Panic(DWinsCPRMStack::EStkIMCBadStateCmd3));
sl@0
   625
				
sl@0
   626
				if (iCardInfo[iAddressedCard]->iIsSDCard)
sl@0
   627
					{
sl@0
   628
					static TUint16 RCACounter = 0x1234;
sl@0
   629
					// SD Cards publish RCAs
sl@0
   630
					++RCACounter;
sl@0
   631
					iCardInfo[iAddressedCard]->iRCA = RCACounter;
sl@0
   632
					iCardInfo[iAddressedCard]->iState = ECardStateStby;
sl@0
   633
					TUint32 r6 = TUint32(RCACounter) << 16;
sl@0
   634
					TMMC::BigEndian4Bytes(&cmd.iResponse[0],r6); // Ignore bits 47-40
sl@0
   635
					}
sl@0
   636
				else
sl@0
   637
					{
sl@0
   638
					iCardInfo[iAddressedCard]->iRCA = TUint16(cmd.iArgument >> 16);
sl@0
   639
					iCardInfo[iAddressedCard]->iState=ECardStateStby;
sl@0
   640
					}
sl@0
   641
				}
sl@0
   642
			else
sl@0
   643
				{
sl@0
   644
				// MultiMediaCards are assigned RCAs
sl@0
   645
				idx = FindOneCardInStack(ECardStateIdent);
sl@0
   646
				iCardInfo[iAddressedCard]->iRCA = TUint16(cmd.iArgument >> 16);
sl@0
   647
				iCardInfo[iAddressedCard]->iState=ECardStateStby;
sl@0
   648
				targetCard = iAddressedCard;
sl@0
   649
				}
sl@0
   650
			}
sl@0
   651
			break;
sl@0
   652
sl@0
   653
		case ECmd6:
sl@0
   654
			// if ACMD6 then change bus width
sl@0
   655
			if (cmd.iSpec.iCommandClass == KMMCCmdClassApplication)
sl@0
   656
				{
sl@0
   657
				switch (cmd.iArgument)
sl@0
   658
					{
sl@0
   659
				case 0x00:
sl@0
   660
					iCardInfo[iAddressedCard]->iBusWidth = 1;
sl@0
   661
					break;
sl@0
   662
				case 0x02:
sl@0
   663
					iCardInfo[iAddressedCard]->iBusWidth = 4;
sl@0
   664
					break;
sl@0
   665
				default:
sl@0
   666
					DWinsCPRMStack::Panic(DWinsCPRMStack::EStkIMCCmd6InvalidWidth);
sl@0
   667
					break;
sl@0
   668
					}
sl@0
   669
				}
sl@0
   670
			break;
sl@0
   671
sl@0
   672
		case ECmdSelectCard:		// CMD7
sl@0
   673
			{
sl@0
   674
			// switch to broadcast mode so the currently selected and new cards
sl@0
   675
			// receive the command simultaneously.
sl@0
   676
sl@0
   677
			TInt idx = FindAnyCardInStack(ECardStateTran);
sl@0
   678
			if (idx != -1)
sl@0
   679
				iCardInfo[idx]->iState = ECardStateStby;
sl@0
   680
			if ((iAddressedCard=targetCard) == KBroadcastToAllCards)
sl@0
   681
				rto = ETrue;
sl@0
   682
			else
sl@0
   683
				{
sl@0
   684
				iCardInfo[targetCard]->iState = ECardStateTran;
sl@0
   685
				targetCard = targetCard;
sl@0
   686
				}
sl@0
   687
			}
sl@0
   688
			break;
sl@0
   689
sl@0
   690
		case ECmdSendStatus:
sl@0
   691
			// R1 response so status return as for any other R1 command.
sl@0
   692
			if (cmd.iSpec.iCommandClass == KMMCCmdClassApplication)
sl@0
   693
				{
sl@0
   694
				__ASSERT_DEBUG(
sl@0
   695
					iCardInfo[targetCard]->iIsSDCard,
sl@0
   696
					DWinsCPRMStack::Panic(DWinsCPRMStack::EStkICMACMD13NotSD));
sl@0
   697
sl@0
   698
				memset(cmd.iDataMemoryP, 0, KSDStatusBlockLength);
sl@0
   699
				if (iCardInfo[targetCard]->iBusWidth == 1)
sl@0
   700
					cmd.iDataMemoryP[0] = 0x00 << 6;
sl@0
   701
				else	// if (iCardInfo[targetCard]->iBusWidth == 4)
sl@0
   702
					cmd.iDataMemoryP[0] = 0x02 << 6;
sl@0
   703
				cmd.iDataMemoryP[7] = 0x28;		// PROTECTED_AREA_SIZE
sl@0
   704
				}
sl@0
   705
			break;
sl@0
   706
sl@0
   707
		case ECmdReadSingleBlock:
sl@0
   708
		case ECmdReadMultipleBlock:
sl@0
   709
			{
sl@0
   710
			winHandle=iCardInfo[targetCard]->iAreaHandles[KSDUserArea];
sl@0
   711
sl@0
   712
			if ( cmd.iSpec.iUseStopTransmission && cmd.iBlockLength >= cmd.iTotalLength)
sl@0
   713
				return( KMMCErrNotSupported );
sl@0
   714
sl@0
   715
    		TMMCErr err;
sl@0
   716
			TInt pos = cmd.iArgument;
sl@0
   717
    		if (SetFilePointer(winHandle,pos,NULL,FILE_BEGIN)==0xffffffffu)
sl@0
   718
        		err=MapLastErrorMmc();
sl@0
   719
    		else
sl@0
   720
        		{
sl@0
   721
	    		DWORD res;
sl@0
   722
				TInt len = cmd.iTotalLength;
sl@0
   723
		        if (ReadFile(winHandle,(TAny*)cmd.iDataMemoryP,len,&res,NULL)==FALSE)
sl@0
   724
                    err=MapLastErrorMmc();
sl@0
   725
                else if (res!=(DWORD)len)
sl@0
   726
                    err=KMMCErrGeneral;
sl@0
   727
                else
sl@0
   728
                    err=KMMCErrNone;
sl@0
   729
				}
sl@0
   730
			if (err!=KMMCErrNone)
sl@0
   731
				return(err);
sl@0
   732
			break;
sl@0
   733
			}
sl@0
   734
sl@0
   735
		case ECmd22:
sl@0
   736
			if (cmd.iSpec.iCommandClass == KMMCCmdClassApplication)
sl@0
   737
				{
sl@0
   738
				TMMC::BigEndian4Bytes(cmd.iResponse, iMBWOKBlocks);
sl@0
   739
				}
sl@0
   740
			break;
sl@0
   741
		// ------------------------------------------------------------------
sl@0
   742
		case ECmdWriteBlock:
sl@0
   743
		case ECmdWriteMultipleBlock:
sl@0
   744
			{
sl@0
   745
			TUint32 writeLen;
sl@0
   746
sl@0
   747
			// periodically fail multi-block writes to test ACMD22 error recovery
sl@0
   748
			if (cmd.iCommand != ECmdWriteMultipleBlock)
sl@0
   749
				writeLen = cmd.iTotalLength;
sl@0
   750
			else
sl@0
   751
				{
sl@0
   752
				const TInt KMaxFailCnt = 4;
sl@0
   753
				static TInt failCnt = 0;
sl@0
   754
				const TInt KMaxFailBlock = 4;
sl@0
   755
				static TInt failBlocks = 0;
sl@0
   756
				
sl@0
   757
				failCnt = (failCnt + 1) % KMaxFailCnt;
sl@0
   758
				if (failCnt != 0)
sl@0
   759
					writeLen = cmd.iTotalLength;
sl@0
   760
				else
sl@0
   761
					{
sl@0
   762
					failBlocks = (failBlocks + 1) % KMaxFailBlock;
sl@0
   763
					
sl@0
   764
					// fail at least one block
sl@0
   765
					TInt totalBlocks = cmd.iTotalLength / cmd.iBlockLength;
sl@0
   766
					TInt blocksToFail = Min(failBlocks + 1, totalBlocks);	// fail at least one block
sl@0
   767
					iMBWOKBlocks = (totalBlocks - blocksToFail);
sl@0
   768
					writeLen = iMBWOKBlocks * cmd.iBlockLength;
sl@0
   769
					if (writeLen == 0)
sl@0
   770
						return KMMCErrDataTimeOut;
sl@0
   771
					}
sl@0
   772
				}
sl@0
   773
			
sl@0
   774
			HANDLE h=iCardInfo[targetCard]->iAreaHandles[KSDUserArea];
sl@0
   775
sl@0
   776
    		TMMCErr err;
sl@0
   777
			TInt pos = cmd.iArgument;
sl@0
   778
    		if (SetFilePointer(h, pos, NULL, FILE_BEGIN)==0xffffffffu)
sl@0
   779
        		err = MapLastErrorMmc();
sl@0
   780
    		else
sl@0
   781
        		{
sl@0
   782
	    		DWORD res;
sl@0
   783
				if (! WriteFile(h, (LPCVOID)cmd.iDataMemoryP,writeLen,&res,NULL))
sl@0
   784
                    err=MapLastErrorMmc();
sl@0
   785
                else if (res!=(DWORD)writeLen)
sl@0
   786
                    err=KMMCErrGeneral;
sl@0
   787
                else
sl@0
   788
                    err=KMMCErrNone;
sl@0
   789
				}
sl@0
   790
sl@0
   791
			if (err!=KMMCErrNone)
sl@0
   792
				return(err);
sl@0
   793
			if (writeLen != cmd.iTotalLength)
sl@0
   794
				return KMMCErrDataTimeOut;
sl@0
   795
			}
sl@0
   796
			break;
sl@0
   797
sl@0
   798
		case ECmdAppCmd:
sl@0
   799
			// targetCard == -1 when ACMD41 being sent because not yet supplied
sl@0
   800
			if (iAddressedCard != KBroadcastToAllCards)
sl@0
   801
				{
sl@0
   802
				// timeout if addressed card is not SD
sl@0
   803
				if (! iCardInfo[iAddressedCard]->iIsSDCard)
sl@0
   804
					rto = ETrue;
sl@0
   805
				}
sl@0
   806
			else
sl@0
   807
				{
sl@0
   808
				// request sent to specific non-SD card
sl@0
   809
				if (targetCard != -1 && ! iCardInfo[targetCard]->iIsSDCard)
sl@0
   810
					rto = ETrue;
sl@0
   811
				}
sl@0
   812
			break;
sl@0
   813
sl@0
   814
		case ECmdSendCSD:
sl@0
   815
			{
sl@0
   816
			iCardInfo[targetCard]->GetCSD(cmd.iResponse);
sl@0
   817
			break;
sl@0
   818
			}
sl@0
   819
sl@0
   820
		// ------------------------------------------------------------------
sl@0
   821
		case ECmdLockUnlock:
sl@0
   822
			// in EPOC, Lock() does not actually lock the card.  It just sets the
sl@0
   823
			// password.  This means that the card is still accessible to the user,
sl@0
   824
			// but must be unlocked the next time it is powered up.
sl@0
   825
sl@0
   826
			// a real card will transiently go into rcv and prg state while processing
sl@0
   827
			// this command.  When finished, it will fall back into tran state.
sl@0
   828
			// The R1 response is sent immediately after CMD42.  CIMReadWriteBlocksSM()
sl@0
   829
			// sends CMD13 to find out whether or not LOCK_UNLOCK_FAIL was set.
sl@0
   830
sl@0
   831
			// the asserts in this case protect against invalid data being sent from the
sl@0
   832
			// media driver.  A real card would fail these corrupt data blocks.
sl@0
   833
sl@0
   834
			{
sl@0
   835
			const TInt8 cmd_byte(*cmd.iDataMemoryP);
sl@0
   836
			__ASSERT_DEBUG(										// ensure not CLR_PWD && SET_PWD
sl@0
   837
				!((cmd_byte & KMMCLockUnlockClrPwd) && (cmd_byte & KMMCLockUnlockSetPwd)),
sl@0
   838
				DWinsCPRMStack::Panic(DWinsCPRMStack::EWinsMMCCorruptCommand) );
sl@0
   839
			
sl@0
   840
			__ASSERT_DEBUG(										// not actually lock a card
sl@0
   841
				!(cmd_byte & KMMCLockUnlockLockUnlock),
sl@0
   842
				DWinsCPRMStack::Panic(DWinsCPRMStack::EWinsMMCLockAttempt) );
sl@0
   843
sl@0
   844
			if (cmd_byte & KMMCLockUnlockErase)					// ERASE (not supported)
sl@0
   845
				return KMMCErrNotSupported;
sl@0
   846
sl@0
   847
			const TInt8 pwd_len = *(cmd.iDataMemoryP + 1);
sl@0
   848
			const TPtrC8 pwd(cmd.iDataMemoryP + 2, pwd_len);
sl@0
   849
sl@0
   850
			if ((cmd_byte & KMMCLockUnlockClrPwd) != 0)			// CLR_PWD == 1
sl@0
   851
				{
sl@0
   852
				__ASSERT_DEBUG(
sl@0
   853
					pwd_len >= 0 && pwd_len <= KMaxMediaPassword,
sl@0
   854
					DWinsCPRMStack::Panic(DWinsCPRMStack::EWinsMMCCorruptCommand));
sl@0
   855
sl@0
   856
				if (iCardInfo[targetCard]->iIsLocked)						// clear when locked
sl@0
   857
					nextCMD42Failed = ETrue;
sl@0
   858
				else														// clear when unlocked
sl@0
   859
					{
sl@0
   860
					if (iCardInfo[targetCard]->iPWD->Compare(pwd) != 0)		// clear when unlocked with wrong password
sl@0
   861
						nextCMD42Failed = ETrue;
sl@0
   862
					else													// clear when unlocked with right password
sl@0
   863
						{
sl@0
   864
						// Clear from password store 
sl@0
   865
						iCardInfo[targetCard]->iPWD->Zero();
sl@0
   866
						iCardInfo[targetCard]->iIsLocked = EFalse;
sl@0
   867
						nextCMD42Failed = EFalse;
sl@0
   868
						
sl@0
   869
						// Clear from environment settings
sl@0
   870
						TInt cardNum=(targetCard==0) ? *Wins::CurrentPBusDevicePtr() : 0; // Can't be -1 at this stage
sl@0
   871
						SetMediaPasswordEnvironmentVar(MMCSocket()->iSocketNumber,cardNum,*(iCardInfo[targetCard]->iPWD));
sl@0
   872
						}
sl@0
   873
					}
sl@0
   874
				}
sl@0
   875
			else if ((cmd_byte & KMMCLockUnlockSetPwd) == 0)	// SET_PWD == 0: unlock
sl@0
   876
				{
sl@0
   877
				__ASSERT_DEBUG(
sl@0
   878
					pwd_len >= 0 && pwd_len <= KMaxMediaPassword,
sl@0
   879
					DWinsCPRMStack::Panic(DWinsCPRMStack::EWinsMMCCorruptCommand) );
sl@0
   880
				
sl@0
   881
				if (! iCardInfo[targetCard]->iIsLocked)						// unlock when unlocked
sl@0
   882
					nextCMD42Failed = ETrue;
sl@0
   883
				else
sl@0
   884
					{
sl@0
   885
					if (iCardInfo[targetCard]->iPWD->Compare(pwd) != 0)		// unlock when locked with wrong password
sl@0
   886
						nextCMD42Failed = ETrue;
sl@0
   887
					else													// unlock when locked with right password
sl@0
   888
						{
sl@0
   889
						iCardInfo[targetCard]->iIsLocked = EFalse;
sl@0
   890
						nextCMD42Failed = EFalse;
sl@0
   891
						}
sl@0
   892
					}
sl@0
   893
				}
sl@0
   894
			else /* ((cmd_byte & KMMCLockUnlockSetPwd) != 0) */	// SET_PWD == 1
sl@0
   895
				{
sl@0
   896
				__ASSERT_DEBUG(
sl@0
   897
					cmd_byte & KMMCLockUnlockSetPwd,
sl@0
   898
					DWinsCPRMStack::Panic(DWinsCPRMStack::EWinsMMCCorruptCommand) );
sl@0
   899
sl@0
   900
				// if pwd_len < iCardInfo[targetCard]->iPWD->Length() then data block must be invalid.
sl@0
   901
				// This can be caused by bad user input rather than inaccurate formation.
sl@0
   902
				if (!(	pwd_len >= iCardInfo[targetCard]->iPWD->Length()
sl@0
   903
					&&	pwd_len <= iCardInfo[targetCard]->iPWD->Length() + KMaxMediaPassword ))
sl@0
   904
					{
sl@0
   905
					nextCMD42Failed = ETrue;
sl@0
   906
					}
sl@0
   907
				else
sl@0
   908
					{
sl@0
   909
					const TInt old_pwd_len = iCardInfo[targetCard]->iPWD->Length();
sl@0
   910
					TPtrC8 old_pwd(cmd.iDataMemoryP + 2, old_pwd_len);
sl@0
   911
					TPtrC8 new_pwd(cmd.iDataMemoryP + 2 + old_pwd_len, pwd_len - old_pwd_len);
sl@0
   912
sl@0
   913
					// card must not be locked and supplied current password must be correct
sl@0
   914
					if (iCardInfo[targetCard]->iIsLocked || iCardInfo[targetCard]->iPWD->Compare(old_pwd) != 0)
sl@0
   915
						nextCMD42Failed = ETrue;
sl@0
   916
					else
sl@0
   917
						{
sl@0
   918
						// Set in password store
sl@0
   919
						iCardInfo[targetCard]->iPWD->Copy(new_pwd);
sl@0
   920
						nextCMD42Failed = EFalse;
sl@0
   921
						
sl@0
   922
						// Set in environment settings
sl@0
   923
						TInt cardNum=(targetCard==0) ? *Wins::CurrentPBusDevicePtr() : 0; // Can't be -1 at this stage
sl@0
   924
						SetMediaPasswordEnvironmentVar(MMCSocket()->iSocketNumber,cardNum,*(iCardInfo[targetCard]->iPWD));
sl@0
   925
						}
sl@0
   926
					}
sl@0
   927
				}	// else /* ((cmd_byte & KMMCLockUnlockSetPwd) != 0) */
sl@0
   928
			}	// case ECmdLockUnlock
sl@0
   929
		// ------------------------------------------------------------------
sl@0
   930
		default:
sl@0
   931
			break;
sl@0
   932
		}
sl@0
   933
sl@0
   934
	if (rto)
sl@0
   935
		return(KMMCErrResponseTimeOut);
sl@0
   936
sl@0
   937
	cmd.iCommand = origCmd;
sl@0
   938
	// If this is an R1 or R1b response type command then return card status as a response
sl@0
   939
	if (	targetCard != -1
sl@0
   940
		&&	(cmd.iSpec.iResponseType==ERespTypeR1 || cmd.iSpec.iResponseType==ERespTypeR1B) )
sl@0
   941
		{
sl@0
   942
		TUint32 resp(
sl@0
   943
				iCardInfo[targetCard]->iState
sl@0
   944
			|	((iCardInfo[targetCard]->iIsLocked ? 1 : 0) << 25)
sl@0
   945
			|	((lock_unlock_failed ? 1 : 0) << 24) );
sl@0
   946
sl@0
   947
		if (iCMD42Failed)								// previous CMD42
sl@0
   948
			{
sl@0
   949
			resp |= KMMCStatErrLockUnlock;
sl@0
   950
			nextCMD42Failed = EFalse;
sl@0
   951
			}
sl@0
   952
		iCMD42Failed = nextCMD42Failed;
sl@0
   953
		TMMC::BigEndian4Bytes(&cmd.iResponse[0],resp); // Ignore bits 47-40
sl@0
   954
		}
sl@0
   955
	SMF_END
sl@0
   956
	}
sl@0
   957
sl@0
   958
TInt DWinsCPRMStack::FindAnyCardInStack(TMMCardStateEnum aState)
sl@0
   959
//
sl@0
   960
// first first active card in supplied state.  Return -1 if
sl@0
   961
// no active card is in supplied state.
sl@0
   962
//
sl@0
   963
	{
sl@0
   964
	if (iAddressedCard != KBroadcastToAllCards)
sl@0
   965
		return (iCardInfo[iAddressedCard]->iState == aState) ? iAddressedCard : -1;
sl@0
   966
	else
sl@0
   967
		{
sl@0
   968
		for (TInt i = 0; i < KTotalWinsCardSlots; ++i)
sl@0
   969
			{
sl@0
   970
			if (iCardInfo[i]->iState == aState)
sl@0
   971
				return i;
sl@0
   972
			}
sl@0
   973
sl@0
   974
		return -1;
sl@0
   975
		}
sl@0
   976
	}
sl@0
   977
sl@0
   978
TInt DWinsCPRMStack::FindFirstCardInStack(TMMCardStateEnum aState)
sl@0
   979
//
sl@0
   980
// find card which is active on bus and in supplied state.
sl@0
   981
// There can be more than one active card in the the supplied state,
sl@0
   982
// but there should be at least one.
sl@0
   983
//
sl@0
   984
	{
sl@0
   985
	if (iAddressedCard != KBroadcastToAllCards)
sl@0
   986
		{
sl@0
   987
		__ASSERT_DEBUG(iCardInfo[iAddressedCard]->iState == aState, DWinsCPRMStack::Panic(DWinsCPRMStack::EStkFFCNotSelCard));
sl@0
   988
		return iAddressedCard;
sl@0
   989
		}
sl@0
   990
	else
sl@0
   991
		{
sl@0
   992
		TInt idx = -1;
sl@0
   993
		for (TInt i = 0; idx != -1 && i < KTotalWinsCardSlots; ++i)
sl@0
   994
			{
sl@0
   995
			if (iCardInfo[i]->iState == aState)
sl@0
   996
				idx = i;
sl@0
   997
			}
sl@0
   998
sl@0
   999
		__ASSERT_DEBUG(idx != -1, DWinsCPRMStack::Panic(DWinsCPRMStack::EStkFFCNoneSel));
sl@0
  1000
		return idx;
sl@0
  1001
		}
sl@0
  1002
	}
sl@0
  1003
sl@0
  1004
TInt DWinsCPRMStack::FindOneCardInStack(TMMCardStateEnum aState)
sl@0
  1005
//
sl@0
  1006
// find card which is active on bus and in supplied state.
sl@0
  1007
// There should be exactly one active card in the supplied state.
sl@0
  1008
//
sl@0
  1009
	{
sl@0
  1010
	if (iAddressedCard != KBroadcastToAllCards)
sl@0
  1011
		{
sl@0
  1012
		__ASSERT_DEBUG(iCardInfo[iAddressedCard]->iState == aState, DWinsCPRMStack::Panic(DWinsCPRMStack::EStkFOCNotSelCard));
sl@0
  1013
		return iAddressedCard;
sl@0
  1014
		}
sl@0
  1015
	else
sl@0
  1016
		{
sl@0
  1017
		TInt idx = -1;
sl@0
  1018
		for (TInt i = 0; i < KTotalWinsCardSlots; ++i)
sl@0
  1019
			{
sl@0
  1020
			if (iCardInfo[i]->iState == aState)
sl@0
  1021
				{
sl@0
  1022
				__ASSERT_DEBUG(idx == -1, DWinsCPRMStack::Panic(DWinsCPRMStack::EStkFOCMultiSel));
sl@0
  1023
				idx = i;
sl@0
  1024
				}
sl@0
  1025
			}
sl@0
  1026
sl@0
  1027
		__ASSERT_DEBUG(idx != -1, DWinsCPRMStack::Panic(DWinsCPRMStack::EStkFOCNoneSel));
sl@0
  1028
		return idx;
sl@0
  1029
		}
sl@0
  1030
	}
sl@0
  1031
sl@0
  1032
TMMCErr DWinsCPRMStack::CIMCalculateMediaKeySM()
sl@0
  1033
//
sl@0
  1034
// Calculate the Media Key record. 
sl@0
  1035
//
sl@0
  1036
	{
sl@0
  1037
  	enum states
sl@0
  1038
  		{
sl@0
  1039
  		EStBegin=0,
sl@0
  1040
  		EStEnd
sl@0
  1041
  		};
sl@0
  1042
sl@0
  1043
	SMF_BEGIN
sl@0
  1044
sl@0
  1045
  	return( KMMCErrNotSupported );
sl@0
  1046
sl@0
  1047
	SMF_END
sl@0
  1048
	}
sl@0
  1049
sl@0
  1050
TMMCErr DWinsCPRMStack::SetSecureCommandArgumentSM()
sl@0
  1051
//
sl@0
  1052
// Auxilary state machine function called during a secure read/write blocks operation.
sl@0
  1053
// Perform random number generation and setting the secure command argument.
sl@0
  1054
//
sl@0
  1055
	{
sl@0
  1056
  	enum states
sl@0
  1057
  		{
sl@0
  1058
  		EStBegin=0,
sl@0
  1059
  		EStEnd
sl@0
  1060
  		};
sl@0
  1061
sl@0
  1062
	SMF_BEGIN
sl@0
  1063
sl@0
  1064
  	return( KMMCErrNotSupported );
sl@0
  1065
sl@0
  1066
	SMF_END
sl@0
  1067
	}				  
sl@0
  1068
  
sl@0
  1069
sl@0
  1070
// ======== DWinsMMCMediaChange ========
sl@0
  1071
sl@0
  1072
#pragma warning( disable : 4355 )	// this used in initializer list
sl@0
  1073
DWinsMMCMediaChange::DWinsMMCMediaChange(TInt aMediaChangeNum)
sl@0
  1074
	: DMMCMediaChange(aMediaChangeNum),
sl@0
  1075
      iDoorClosedCount(0),
sl@0
  1076
	  iMediaChangeEnable(ETrue),
sl@0
  1077
	  iStackP(NULL)
sl@0
  1078
	{
sl@0
  1079
	iMediaDoorCloseReload=2; 	// Units: In theory-20ms, Actual-100ms
sl@0
  1080
	}
sl@0
  1081
#pragma warning( default : 4355 )
sl@0
  1082
sl@0
  1083
TInt DWinsMMCMediaChange::Create()
sl@0
  1084
//
sl@0
  1085
// Initialiser.
sl@0
  1086
//
sl@0
  1087
	{	
sl@0
  1088
	return(DMediaChangeBase::Create());
sl@0
  1089
	}
sl@0
  1090
sl@0
  1091
void DWinsMMCMediaChange::DoorOpenService()
sl@0
  1092
//
sl@0
  1093
// Handle the media change (this function, never postponed is called on media
sl@0
  1094
// change interrupt). 
sl@0
  1095
//
sl@0
  1096
	{
sl@0
  1097
	Disable();		// Disable interrupt until door closes again.
sl@0
  1098
	iDoorOpenDfc.Enque();
sl@0
  1099
	}
sl@0
  1100
sl@0
  1101
void DWinsMMCMediaChange::DoDoorOpen()
sl@0
  1102
//
sl@0
  1103
// Handle media door open (called on media door open interrupt). 
sl@0
  1104
//
sl@0
  1105
	{
sl@0
  1106
	iDoorClosedCount=iMediaDoorCloseReload;
sl@0
  1107
	// Just start a ticklink to poll for door closing
sl@0
  1108
	iTickLink.Periodic(KMediaChangeTickInterval,DWinsMMCMediaChange::Tick,this);
sl@0
  1109
    }
sl@0
  1110
sl@0
  1111
void DWinsMMCMediaChange::DoDoorClosed()
sl@0
  1112
//
sl@0
  1113
// Handle media door closing (called on media door open interrupt).
sl@0
  1114
//
sl@0
  1115
	{
sl@0
  1116
sl@0
  1117
	iTickLink.Cancel();	// Doesn't matter if wasn't enabled
sl@0
  1118
	Enable();	// Re-enable door interrupts
sl@0
  1119
sl@0
  1120
	// While the door was open the user may have changed the card in slot 0
sl@0
  1121
	if (iStackP && *Wins::CurrentPBusDevicePtr()>=0)
sl@0
  1122
		iStackP->iCardInfo[0]=iStackP->iCardPool[*Wins::CurrentPBusDevicePtr()];
sl@0
  1123
	}
sl@0
  1124
sl@0
  1125
void DWinsMMCMediaChange::ForceMediaChange()
sl@0
  1126
//
sl@0
  1127
// Force media change
sl@0
  1128
//
sl@0
  1129
	{
sl@0
  1130
	DoorOpenService();
sl@0
  1131
	}
sl@0
  1132
sl@0
  1133
TMediaState DWinsMMCMediaChange::MediaState()
sl@0
  1134
//
sl@0
  1135
// Return status of media changed signal.
sl@0
  1136
//
sl@0
  1137
	{
sl@0
  1138
sl@0
  1139
	if (iDoorClosedCount>0)
sl@0
  1140
		return(EDoorOpen);
sl@0
  1141
	return( (*Wins::MediaDoorOpenPtr())?EDoorOpen:EDoorClosed);
sl@0
  1142
	}
sl@0
  1143
sl@0
  1144
void DWinsMMCMediaChange::Tick(TAny *aPtr)
sl@0
  1145
//
sl@0
  1146
// Called on the tick to poll for door closing (called on DFC).
sl@0
  1147
//
sl@0
  1148
	{
sl@0
  1149
sl@0
  1150
	((DWinsMMCMediaChange*)aPtr)->TickService();
sl@0
  1151
	}
sl@0
  1152
sl@0
  1153
void DWinsMMCMediaChange::TickService()
sl@0
  1154
//
sl@0
  1155
// Called on the tick to poll for door closing (called on DFC).
sl@0
  1156
//
sl@0
  1157
	{
sl@0
  1158
sl@0
  1159
	__ASSERT_DEBUG(iDoorClosedCount>=0,DWinsCPRMStack::Panic(DWinsCPRMStack::EWinsMMCMediaChangeTickFault));
sl@0
  1160
	if (!(*Wins::MediaDoorOpenPtr()))
sl@0
  1161
		{
sl@0
  1162
		if (iDoorClosedCount > 0)
sl@0
  1163
			iDoorClosedCount--;
sl@0
  1164
		if (iDoorClosedCount == 0)
sl@0
  1165
			DoorClosedService();
sl@0
  1166
		}
sl@0
  1167
	else
sl@0
  1168
		iDoorClosedCount=iMediaDoorCloseReload; // Door open so start again.
sl@0
  1169
	}
sl@0
  1170
sl@0
  1171
void DWinsMMCMediaChange::Enable()
sl@0
  1172
//
sl@0
  1173
// Enable media change 
sl@0
  1174
//
sl@0
  1175
	{
sl@0
  1176
sl@0
  1177
	iMediaChangeEnable=ETrue;
sl@0
  1178
	}
sl@0
  1179
sl@0
  1180
void DWinsMMCMediaChange::Disable()
sl@0
  1181
//
sl@0
  1182
// Disable media change
sl@0
  1183
//
sl@0
  1184
	{
sl@0
  1185
sl@0
  1186
	iMediaChangeEnable=EFalse;
sl@0
  1187
	}
sl@0
  1188
sl@0
  1189
void DWinsMMCMediaChange::MediaChangeCallBack(TAny *aPtr)
sl@0
  1190
//
sl@0
  1191
// Static called on media change
sl@0
  1192
//
sl@0
  1193
	{
sl@0
  1194
sl@0
  1195
	DWinsMMCMediaChange* mc=(DWinsMMCMediaChange*)aPtr;
sl@0
  1196
	if (mc!=NULL&&mc->iMediaChangeEnable)
sl@0
  1197
		mc->DoorOpenService();
sl@0
  1198
	}
sl@0
  1199
sl@0
  1200
sl@0
  1201
// ======== TWinsCardInfo ========
sl@0
  1202
sl@0
  1203
void TWinsCardInfo::GetCSD(TUint8* aResp) const
sl@0
  1204
	{
sl@0
  1205
	// Bits 127-96
sl@0
  1206
	TUint32 csd=(0x1<<30); 	/* CSD_STRUCTURE: CSD Version No 1.1 */
sl@0
  1207
	csd|=		(0x2<<26); 	/* SPEC_VERS: Version 2.1 */
sl@0
  1208
	csd|=		(0x0E<<16);	/* TAAC: 1mS */  
sl@0
  1209
	csd|=		(0x0A<<8);	/* NSAC: 1000 */  
sl@0
  1210
	csd|=		(0x59);		/* TRAN_SPEED: 5.0Mbit/s */  
sl@0
  1211
	TMMC::BigEndian4Bytes(&aResp[0],csd);
sl@0
  1212
	// Bits 95-64
sl@0
  1213
	const TUint32 ccc = 
sl@0
  1214
			KMMCCmdClassBasic | KMMCCmdClassBlockRead
sl@0
  1215
		|	KMMCCmdClassBlockWrite | KMMCCmdClassLockCard;
sl@0
  1216
	csd=		(ccc<<20); 	/* CCC: classes 0, 2, 4, and 7 */
sl@0
  1217
	csd|=		(0x9<<16); 	/* READ_BL_LEN: 512 bytes */
sl@0
  1218
	csd|=		(0x0<<15);	/* READ_BL_PARTIAL: No */  
sl@0
  1219
	csd|=		(0x0<<14);	/* WRITE_BLK_MISALIGN: No */  
sl@0
  1220
	csd|=		(0x0<<13);	/* READ_BLK_MISALIGN: No */  
sl@0
  1221
	csd|=		(0x0<<12);	/* DSR_IMP: No DSR */ 
sl@0
  1222
	csd|=		(0x0<<8);	/* C_SIZE: 1Mb */
sl@0
  1223
	csd|=		(0x7F);		/* C_SIZE: 1Mb (cont)*/  
sl@0
  1224
	TMMC::BigEndian4Bytes(&aResp[4],csd); 
sl@0
  1225
	// Bits 63-32
sl@0
  1226
	csd=		(3UL<<30); 	/* C_SIZE: 2Mb (cont) */
sl@0
  1227
	csd|=		(0x1<<27); 	/* VDD_R_CURR_MIN: 1mA */
sl@0
  1228
	csd|=		(0x1<<24);	/* VDD_R_CURR_MAX: 5mA */  
sl@0
  1229
	csd|=		(0x2<<21); 	/* VDD_W_CURR_MIN: 5mA */
sl@0
  1230
	csd|=		(0x3<<18);	/* VDD_W_CURR_MAX: 25mA */  
sl@0
  1231
	csd|=		(0x0<<15);	/* C_SIZE_MULT: 0 */  
sl@0
  1232
	if (! iIsSDCard)
sl@0
  1233
		{
sl@0
  1234
		csd|=		(0x0<<10);	/* SECTOR_SIZE: 1 write block */  
sl@0
  1235
		csd|=		(0x0<<5);	/* ERASE_GRP_SIZE: 1 sector */  
sl@0
  1236
		csd|=		(0x0);		/* WP_GRP_SIZE: 1 erase group */  
sl@0
  1237
		}
sl@0
  1238
	else
sl@0
  1239
		{
sl@0
  1240
		csd |= (0x00 << (46 - 32));	// ERASE_BLK_EN
sl@0
  1241
		csd |= (0x1f << (39 - 32));	// SECTOR_SIZE: 32 write blocks
sl@0
  1242
		csd |= (0x00 << (32 - 32));	// WP_GRP_SIZE: 1 erase sector.
sl@0
  1243
		}
sl@0
  1244
	TMMC::BigEndian4Bytes(&aResp[8],csd); 
sl@0
  1245
	// Bits 31-0
sl@0
  1246
	csd=		(0x0<<31); 	/* WP_GRP_ENABLE: No */
sl@0
  1247
	csd|=		(0x0<<29); 	/* DEFAULT_ECC: ? */
sl@0
  1248
	csd|=		(0x3<<26);	/* R2W_FACTOR: 8 */  
sl@0
  1249
	csd|=		(0x9<<22); 	/* WRITE_BL_LEN: 512 bytes */
sl@0
  1250
	csd|=		(0x0<<21);	/* WRITE_BL_PARTIAL: No */  
sl@0
  1251
	csd|=		(0x0<<15);	/* FILE_FORMAT_GRP: Hard disk */  
sl@0
  1252
	csd|=		(0x0<<14);	/* COPY: original */  
sl@0
  1253
	csd|=		(0x0<<13);	/* PERM_WRITE_PROTECT: No */  
sl@0
  1254
	csd|=		(0x0<<12);	/* TMP_WRITE_PROTECT: No */  
sl@0
  1255
	csd|=		(0x0<<10);	/* FILE_FORMAT: Hard disk */  
sl@0
  1256
	csd|=		(0x0<<8);	/* ECC: None */  
sl@0
  1257
	csd|=		(0x0<<1);	/* CRC: ? */  
sl@0
  1258
	csd|=		(0x1);		/* not used */  
sl@0
  1259
	TMMC::BigEndian4Bytes(&aResp[12],csd);
sl@0
  1260
	}
sl@0
  1261
sl@0
  1262
// ======== DWinsMMCPsu ========
sl@0
  1263
sl@0
  1264
sl@0
  1265
DWinsMMCPsu::DWinsMMCPsu(TInt aVccNum, TInt aMcId)
sl@0
  1266
	: DMMCPsu(aVccNum, aMcId)
sl@0
  1267
	{}
sl@0
  1268
sl@0
  1269
void DWinsMMCPsu::Init()
sl@0
  1270
//
sl@0
  1271
// Initialise the PSU
sl@0
  1272
//
sl@0
  1273
    {
sl@0
  1274
	// Nothing to do
sl@0
  1275
    }
sl@0
  1276
sl@0
  1277
void DWinsMMCPsu::DoSetState(TPBusPsuState aState)
sl@0
  1278
//
sl@0
  1279
// Turn on/off the PSU. If it is possible to adjust the output voltage on this
sl@0
  1280
// PSU then retreive the required voltage level from TMMCPsu::iVoltageSetting
sl@0
  1281
// (which is in OCR register format).
sl@0
  1282
//
sl@0
  1283
    {
sl@0
  1284
sl@0
  1285
    switch (aState)
sl@0
  1286
        {
sl@0
  1287
        case EPsuOff:
sl@0
  1288
            break;
sl@0
  1289
        case EPsuOnFull:
sl@0
  1290
            break;
sl@0
  1291
        case EPsuOnCurLimit:
sl@0
  1292
            break;
sl@0
  1293
        }
sl@0
  1294
    }
sl@0
  1295
sl@0
  1296
TInt DWinsMMCPsu::VoltageInMilliVolts()
sl@0
  1297
//
sl@0
  1298
// Return the level of the PSU (in mV) or -ve if error.
sl@0
  1299
//
sl@0
  1300
    {
sl@0
  1301
sl@0
  1302
    return(0);
sl@0
  1303
    }
sl@0
  1304
sl@0
  1305
void DWinsMMCPsu::DoCheckVoltage()
sl@0
  1306
//
sl@0
  1307
// Check the voltage level of the PSU is as expected. Returns either KErrNone, KErrGeneral 
sl@0
  1308
// to indicate the pass/fail state or KErrNotReady if the voltage check isn't complete.
sl@0
  1309
//
sl@0
  1310
    {
sl@0
  1311
sl@0
  1312
	ReceiveVoltageCheckResult(KErrNone);
sl@0
  1313
    }
sl@0
  1314
sl@0
  1315
void DWinsMMCPsu::PsuInfo(TPBusPsuInfo &anInfo)
sl@0
  1316
//
sl@0
  1317
// Return machine info relating to the MMC PSU supply
sl@0
  1318
//
sl@0
  1319
    {
sl@0
  1320
sl@0
  1321
	anInfo.iVoltageSupported=0x00040000; // 3.0V (OCR reg. format).
sl@0
  1322
	anInfo.iMaxCurrentInMicroAmps=0;
sl@0
  1323
	anInfo.iVoltCheckInterval=0;
sl@0
  1324
	anInfo.iVoltCheckMethod=EPsuChkComparator;
sl@0
  1325
    anInfo.iNotLockedTimeOut=0;  // Not enabled
sl@0
  1326
	anInfo.iInactivityTimeOut=5; // 5 Seconds
sl@0
  1327
    }