os/boardsupport/emulator/emulatorbsp/specific/mmc.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
// PP_MMC.CPP
sl@0
    15
// 
sl@0
    16
//
sl@0
    17
sl@0
    18
#include "plat_priv.h"
sl@0
    19
#include <property.h>
sl@0
    20
#include "variant.h"
sl@0
    21
#include "variantmediadef.h"
sl@0
    22
#include "mmci.h" 
sl@0
    23
sl@0
    24
//#define  __CARD0_NOT_LOCKABLE__
sl@0
    25
//#define  __CARD1_NOT_LOCKABLE__
sl@0
    26
sl@0
    27
const TInt  KDiskSectorSize=512;
sl@0
    28
sl@0
    29
TInt  DWinsMMCStack::TotalMDiskSize=0;		///< mmc card size for emulator
sl@0
    30
TUint DWinsMMCStack::CSIZE=0;				///< mmc card size field
sl@0
    31
TUint DWinsMMCStack::CSIZE_MULT=0;			///< mmc card size field
sl@0
    32
sl@0
    33
TInt  DWinsMMCStack::TotalWinsMMC_CardSlots = KDefault_TotalWinsCardSlots; ///< total number of MMC card slots for the emulator
sl@0
    34
TInt  DWinsMMCStack::TotalWinsMMC_Cards     = KDefault_TotalWinsCards;     ///< total number of MMC cards for the emulator
sl@0
    35
sl@0
    36
sl@0
    37
const TUint32 KCsdStructure = 0x01;	/* CSD Version No 1.1 */
sl@0
    38
const TUint32 KCsdSpecVers  = 0x03;	/* Version 3.1 */
sl@0
    39
sl@0
    40
TInt MapLastErrorEpoc()
sl@0
    41
//
sl@0
    42
// Map an NT error to an Epoc/32 error.
sl@0
    43
//
sl@0
    44
	{
sl@0
    45
	TInt res=KErrGeneral;
sl@0
    46
	switch (GetLastError())
sl@0
    47
		{
sl@0
    48
		case ERROR_SHARING_VIOLATION : res=KErrAccessDenied; break;
sl@0
    49
		case ERROR_LOCK_VIOLATION : res=KErrLocked; break;
sl@0
    50
		case ERROR_FILE_NOT_FOUND: res=KErrNotFound; break;
sl@0
    51
		case ERROR_PATH_NOT_FOUND: res=KErrPathNotFound; break;
sl@0
    52
		case ERROR_ALREADY_EXISTS:
sl@0
    53
		case ERROR_FILE_EXISTS:
sl@0
    54
			res=KErrAlreadyExists;
sl@0
    55
			break;
sl@0
    56
		case ERROR_NOT_READY: res=KErrNotReady; break;
sl@0
    57
		case ERROR_UNRECOGNIZED_VOLUME:
sl@0
    58
		case ERROR_NOT_DOS_DISK:
sl@0
    59
			res=KErrUnknown;
sl@0
    60
			break;
sl@0
    61
		case ERROR_UNRECOGNIZED_MEDIA: res=KErrCorrupt; break;
sl@0
    62
		case ERROR_INVALID_NAME: res=KErrBadName; break;
sl@0
    63
		case ERROR_NO_MORE_FILES: res=KErrEof; break;
sl@0
    64
		}
sl@0
    65
	return(res);
sl@0
    66
	}
sl@0
    67
sl@0
    68
TMMCErr MapLastErrorMmc()
sl@0
    69
//
sl@0
    70
// Map an NT error to a TMMCErr error.
sl@0
    71
//
sl@0
    72
	{
sl@0
    73
	DWORD r=GetLastError();
sl@0
    74
	TInt res=KErrGeneral;
sl@0
    75
	switch (r)
sl@0
    76
		{
sl@0
    77
		case ERROR_SHARING_VIOLATION:
sl@0
    78
		case ERROR_LOCK_VIOLATION:
sl@0
    79
			res=KMMCErrLocked;			// KErrLocked
sl@0
    80
			break;
sl@0
    81
		case ERROR_FILE_NOT_FOUND:
sl@0
    82
		case ERROR_PATH_NOT_FOUND:
sl@0
    83
			res=KMMCErrNotFound;		// KErrNotFound
sl@0
    84
			break;
sl@0
    85
		case ERROR_ALREADY_EXISTS:
sl@0
    86
		case ERROR_FILE_EXISTS:
sl@0
    87
			res=KMMCErrAlreadyExists;	// KErrAlreadyExists
sl@0
    88
			break;
sl@0
    89
		case ERROR_NOT_READY: res=KMMCErrNoCard; break;
sl@0
    90
		case ERROR_UNRECOGNIZED_VOLUME:
sl@0
    91
		case ERROR_NOT_DOS_DISK:
sl@0
    92
			res=KMMCErrGeneral;			// KErrGeneral
sl@0
    93
			break;
sl@0
    94
		case ERROR_UNRECOGNIZED_MEDIA:
sl@0
    95
		case ERROR_INVALID_NAME:
sl@0
    96
		case ERROR_NO_MORE_FILES:
sl@0
    97
			res=KMMCErrResponseCRC; 	// KErrCorrupt
sl@0
    98
			break;
sl@0
    99
		}
sl@0
   100
	return(res);
sl@0
   101
	}
sl@0
   102
sl@0
   103
sl@0
   104
void DWinsMMCStack::MachineInfo(TMMCMachineInfo& aMachineInfo)
sl@0
   105
//
sl@0
   106
// Return machine info relating to this MultiMediaCard Stack
sl@0
   107
//
sl@0
   108
	{
sl@0
   109
	aMachineInfo.iTotalSockets=TotalWinsMMC_CardSlots;
sl@0
   110
	aMachineInfo.iTotalMediaChanges=0;  		// Not used at present
sl@0
   111
	aMachineInfo.iTotalPrimarySupplies=0;		// Not used at present
sl@0
   112
sl@0
   113
	aMachineInfo.iFlags = TMMCMachineInfo::ESupportsDoubleBuffering;
sl@0
   114
    aMachineInfo.iBaseBusNumber=0;
sl@0
   115
sl@0
   116
	__KTRACE_OPT(KPBUS1,Kern::Printf("<WinsMMC:MachineInfo"));
sl@0
   117
	__KTRACE_OPT(KPBUS1,Kern::Printf(" %d stacks",aMachineInfo.iTotalSockets));
sl@0
   118
sl@0
   119
	__ASSERT_DEBUG(aMachineInfo.iTotalSockets<=KMaxMMCardsPerStack,Panic(EWinsMMCBadMachineInfo));
sl@0
   120
	}
sl@0
   121
sl@0
   122
void DWinsMMCStack::AdjustPartialRead(
sl@0
   123
	const TMMCard* aCard, TUint32 aStart, 
sl@0
   124
#ifdef _DEBUG
sl@0
   125
	TUint32 aEnd, 
sl@0
   126
#else
sl@0
   127
	TUint32 /*aEnd*/, 
sl@0
   128
#endif
sl@0
   129
	TUint32* aPhysStart, TUint32* aPhysEnd) const
sl@0
   130
	{
sl@0
   131
	const TUint32 blkLen = 1 << aCard->MaxReadBlLen();
sl@0
   132
	const TUint32 blkMsk = blkLen - 1;
sl@0
   133
#ifdef _DEBUG
sl@0
   134
	__ASSERT_DEBUG(aCard->CSD().ReadBlPartial(), Panic(EWinsMMCAPRNotSupp));
sl@0
   135
	__ASSERT_DEBUG(aEnd - aStart <= blkLen, Panic(EWinsMMCAPRRange));
sl@0
   136
	__ASSERT_DEBUG((aEnd & ~blkMsk) > (aStart & ~blkMsk), Panic(EWinsMMCAPRBoundary));
sl@0
   137
#endif
sl@0
   138
sl@0
   139
	*aPhysStart = aStart & ~blkMsk;
sl@0
   140
	*aPhysEnd = *aPhysStart + blkLen;
sl@0
   141
	}
sl@0
   142
sl@0
   143
void DWinsMMCStack::GetBufferInfo(TUint8** aMDBuf, TInt* aMDBufLen)
sl@0
   144
	{
sl@0
   145
	*aMDBuf = iMDBuf;
sl@0
   146
	*aMDBufLen = iMDBufLen;
sl@0
   147
	}
sl@0
   148
sl@0
   149
void DWinsMMCStack::Panic(TWinsMMCPanic aPanic)
sl@0
   150
	{
sl@0
   151
	_LIT(KPncNm,"PBUS-MMC-WINS");
sl@0
   152
	Kern::PanicCurrentThread(KPncNm,aPanic);
sl@0
   153
	}
sl@0
   154
sl@0
   155
DWinsMMCStack::DWinsMMCStack(TInt aBus, DMMCSocket* aSocket)
sl@0
   156
	          :DMMCStack(aBus, aSocket)
sl@0
   157
	{
sl@0
   158
	
sl@0
   159
//	iAddressedCard=0;
sl@0
   160
//	iSecureArgDevAddr=0;
sl@0
   161
//	iSecureArgTotalLength=0;
sl@0
   162
//	iCMD42Failed=EFalse;
sl@0
   163
	}
sl@0
   164
sl@0
   165
sl@0
   166
/**
sl@0
   167
    Allocate cards.  Only called at bootup, so no cleanup if fails.
sl@0
   168
*/
sl@0
   169
TInt DWinsMMCStack::Init()
sl@0
   170
	{
sl@0
   171
	 
sl@0
   172
    //-- try to read number of mmc cards and slots from epoc.ini file
sl@0
   173
    const TInt MmcSlots = Property::GetInt("MultiMediaCardSlots");
sl@0
   174
    const TInt MmcCards = Property::GetInt("MultiMediaCardsNum");
sl@0
   175
    
sl@0
   176
    if(MmcSlots == 0 && MmcCards == 0)
sl@0
   177
        {//-- parameters not specified, do nothing; static variables are initialized with default values
sl@0
   178
        }
sl@0
   179
    else
sl@0
   180
        {
sl@0
   181
        if((MmcSlots == 0 && MmcCards >0) || (MmcSlots > 0 && MmcCards ==0))
sl@0
   182
            {//-- only one of the parameters is specified. use it as "Cards quantity"
sl@0
   183
            TotalWinsMMC_Cards     = Max(MmcSlots, MmcCards); //-- chose non zero value
sl@0
   184
            TotalWinsMMC_CardSlots = Max(1, TotalWinsMMC_Cards-1);
sl@0
   185
            }
sl@0
   186
        else
sl@0
   187
            {//-- both parameters are specified
sl@0
   188
            TotalWinsMMC_Cards     = MmcCards;
sl@0
   189
            TotalWinsMMC_CardSlots = MmcSlots;
sl@0
   190
            }
sl@0
   191
    
sl@0
   192
        }//if(!MmcSlots && !MmcCards)
sl@0
   193
sl@0
   194
    TotalWinsMMC_Cards      = Min(TotalWinsMMC_Cards, KMax_TotalWinsCards);
sl@0
   195
    TotalWinsMMC_CardSlots  = Min(TotalWinsMMC_CardSlots, KMax_TotalWinsCardSlots);
sl@0
   196
sl@0
   197
    
sl@0
   198
    if((iCardArray = new TMMCardArray(this)) == NULL)
sl@0
   199
		return KErrNoMemory;
sl@0
   200
sl@0
   201
	TInt r=DMMCStack::Init();
sl@0
   202
	if(r!=KErrNone)
sl@0
   203
		return r;
sl@0
   204
sl@0
   205
	DMediaChangeBase* pMCBase = MMCSocket()->iMediaChange;
sl@0
   206
	static_cast<DWinsMMCMediaChange*>(pMCBase)->SetStackP(this);
sl@0
   207
	Wins::SetMediaChangeCallBackPtr(DWinsMMCMediaChange::MediaChangeCallBack, (TAny*)pMCBase);
sl@0
   208
sl@0
   209
	//
sl@0
   210
	// Over time memory can become fragmented, and so it is not possible to
sl@0
   211
	// allocate physically contiguous pages.  Therefore, the buffers for IO
sl@0
   212
	// are allocated at startup.
sl@0
   213
	//
sl@0
   214
	// For the WINS implementation, fragmentation does not matter because
sl@0
   215
	// DMA is not used.  The memory must still be allocated here so MEDMMC is
sl@0
   216
	// able to use it.
sl@0
   217
	//
sl@0
   218
	// The constant calculations could be folded, but this illustrates how the
sl@0
   219
	// values are derived.
sl@0
   220
	//
sl@0
   221
sl@0
   222
	// MMC only - values from Hitachi 16Mb card, datasheet HB288016MM1
sl@0
   223
sl@0
   224
	// minor buffer must contain enough space for MBR or block
sl@0
   225
	const TUint mmcBlkSzLog2 = 9;				// READ_BLK_LEN and WRITE_BLK_LEN
sl@0
   226
	const TUint mmcBlkSz = 1 << mmcBlkSzLog2;
sl@0
   227
	const TInt mmcMinorBufLen = Max(KDiskSectorSize, mmcBlkSz);
sl@0
   228
sl@0
   229
	// There are 2 slots each with up to 2 media drivers; we allocate 8 blocks for each driver.
sl@0
   230
	// It is the media drivers' responsibility to devide up the buffer space according 
sl@0
   231
	// to which slot number is allocated to it (DMmcMediaDriverFlash::iCardNumber)
sl@0
   232
	const TInt KMinMMCBlocksInBuffer = 16 * MMC0_NUMMEDIA;
sl@0
   233
	const TInt mmcCchBufLen = KMinMMCBlocksInBuffer << mmcBlkSzLog2;
sl@0
   234
sl@0
   235
	const TInt mmcTotalBufLen = mmcMinorBufLen + mmcCchBufLen;
sl@0
   236
sl@0
   237
	const TInt totalBufLen = mmcTotalBufLen;
sl@0
   238
sl@0
   239
	iMDBuf = reinterpret_cast<TUint8*>(Kern::Alloc(totalBufLen));
sl@0
   240
	iMDBufLen = totalBufLen;
sl@0
   241
sl@0
   242
	// setup card size parameters from epoc.ini
sl@0
   243
	if (TotalMDiskSize==0)
sl@0
   244
		{
sl@0
   245
		// Static member variable TotalMDiskSize initialised to zero by default. Set 
sl@0
   246
		// up static member variables TotalMDiskSize, CSIZE and CSIZE_MULT once and 
sl@0
   247
		// once only. Use INI file setting if available. Else set to default, IMb.
sl@0
   248
		TUint cardSize = Property::GetInt("MultiMediaCardSize");
sl@0
   249
		if (cardSize)
sl@0
   250
			{
sl@0
   251
			// set values to match epoc.ini settings
sl@0
   252
			SetupDiskParms(cardSize);
sl@0
   253
			}		
sl@0
   254
		else
sl@0
   255
			{
sl@0
   256
			// set default values for 1 MB drive
sl@0
   257
			TotalMDiskSize=0x100000;
sl@0
   258
			CSIZE=127;
sl@0
   259
			CSIZE_MULT=2;
sl@0
   260
			}
sl@0
   261
		}
sl@0
   262
sl@0
   263
	// Initialise each virtual card that will be used on this stack.
sl@0
   264
	TInt i;
sl@0
   265
	for (i=0 ; i<TotalWinsMMC_Cards; i++)
sl@0
   266
		{
sl@0
   267
		if ((r=SetupSimulatedCard(i))!=KErrNone)
sl@0
   268
			return(r);
sl@0
   269
		}
sl@0
   270
sl@0
   271
	// initialize pointers to currently present cards
sl@0
   272
sl@0
   273
	// Slot zero can toggle between no card; card 0 and card 1.  The current state is
sl@0
   274
	// determined by *Kern::CurrentPBusDevicePtr() and toggled by pressing F4 when F5
sl@0
   275
	// (door open) is held down.  Because this function is only executed at startup,
sl@0
   276
	// assume start with card zero.
sl@0
   277
	iCardInfo[0] = iCardPool[0];
sl@0
   278
	for (i = 1; i < TotalWinsMMC_CardSlots; ++i)
sl@0
   279
		{
sl@0
   280
		iCardInfo[i]=iCardPool[i+1];
sl@0
   281
		}
sl@0
   282
sl@0
   283
	return(KErrNone);
sl@0
   284
	}
sl@0
   285
sl@0
   286
sl@0
   287
TInt DWinsMMCStack::CreateBinFileForCard(TInt aCardNum,HANDLE* aHandle,TBool aCreateNew)
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(_L8("A.BIN"));
sl@0
   300
	fn8.Append('\0');
sl@0
   301
	*aHandle = CreateFileA(
sl@0
   302
		(LPCSTR) fn8.Ptr(),							// LPCSTR lpFileName,
sl@0
   303
		GENERIC_READ | GENERIC_WRITE,				// DWORD dwDesiredAccess
sl@0
   304
		FILE_SHARE_READ | FILE_SHARE_WRITE,			// DWORD dwShareMode
sl@0
   305
		NULL,										// LPSECURITY_ATTRIBUTES lpSecurityAttributes
sl@0
   306
		aCreateNew ? CREATE_ALWAYS : OPEN_ALWAYS,	// DWORD dwCreationDisposition
sl@0
   307
		FILE_FLAG_RANDOM_ACCESS,					// DWORD dwFlagsAndAttributes
sl@0
   308
			NULL);									// HANDLE hTemplateFile
sl@0
   309
	
sl@0
   310
	TInt fileSize=GetFileSize(*aHandle,NULL);
sl@0
   311
	if (fileSize>TotalMDiskSize)
sl@0
   312
		//
sl@0
   313
		// The Drive file already exists and size of emulated drive as configured in 
sl@0
   314
		// epoc.ini has been reduced. Musn't corrupt the emulated drive so delete the 
sl@0
   315
		// drive file and start from scratch. The emulated drive contents will be 
sl@0
   316
		// erased.
sl@0
   317
		//
sl@0
   318
		{
sl@0
   319
		CloseHandle(*aHandle);
sl@0
   320
		DeleteFileA(
sl@0
   321
			(LPCSTR) fn8.Ptr());						// LPCSTR lpFileName,			
sl@0
   322
		*aHandle = CreateFileA(
sl@0
   323
			(LPCSTR) fn8.Ptr(),							// LPCSTR lpFileName,
sl@0
   324
			GENERIC_READ | GENERIC_WRITE,				// DWORD dwDesiredAccess
sl@0
   325
			FILE_SHARE_READ | FILE_SHARE_WRITE,			// DWORD dwShareMode
sl@0
   326
			NULL,										// LPSECURITY_ATTRIBUTES lpSecurityAttributes
sl@0
   327
			aCreateNew ? CREATE_ALWAYS : OPEN_ALWAYS,	// DWORD dwCreationDisposition
sl@0
   328
			FILE_FLAG_RANDOM_ACCESS,					// DWORD dwFlagsAndAttributes
sl@0
   329
				NULL);									// HANDLE hTemplateFile
sl@0
   330
		}
sl@0
   331
sl@0
   332
	if (*aHandle==INVALID_HANDLE_VALUE)
sl@0
   333
		return(MapLastErrorEpoc());
sl@0
   334
sl@0
   335
	if (SetFilePointer(*aHandle,TotalMDiskSize,NULL,FILE_BEGIN)==0xffffffffu
sl@0
   336
		||	! SetEndOfFile(*aHandle) )
sl@0
   337
		{
sl@0
   338
		CloseHandle(*aHandle);
sl@0
   339
	    return(MapLastErrorEpoc());
sl@0
   340
		}
sl@0
   341
sl@0
   342
	return KErrNone;
sl@0
   343
	}
sl@0
   344
sl@0
   345
sl@0
   346
TInt DWinsMMCStack::SetupSimulatedCard(TInt aCardNum)
sl@0
   347
//
sl@0
   348
// allocate individual card with Win32 file.  Only called at bootup, so no cleanup if fails.
sl@0
   349
//
sl@0
   350
	{
sl@0
   351
	TWinsCardInfo* cip = new TWinsCardInfo;
sl@0
   352
	if (cip == 0)
sl@0
   353
		return(KErrNoMemory);
sl@0
   354
sl@0
   355
	TUint8 cid[KMMCCIDLength];
sl@0
   356
	cid[0] = 'C';
sl@0
   357
	cid[1] = 'I';
sl@0
   358
	cid[2] = 'D';
sl@0
   359
	cid[3] = TUint8('0' + aCardNum);
sl@0
   360
	TInt j;
sl@0
   361
	for (j = 4; j < KMMCCIDLength - 1; ++j)
sl@0
   362
		cid[j] = 'c';
sl@0
   363
	cid[KMMCCIDLength - 1] = '#';				// '#' = 0x23, bit zero must be 1
sl@0
   364
	cip->iCID=cid;
sl@0
   365
sl@0
   366
	cip->iPWD=new TMediaPassword;
sl@0
   367
	if (!cip->iPWD)
sl@0
   368
		{
sl@0
   369
		delete cip;
sl@0
   370
		return(KErrNoMemory);
sl@0
   371
		}
sl@0
   372
sl@0
   373
	cip->iState=ECardStateIdle;
sl@0
   374
sl@0
   375
	HANDLE h=NULL;
sl@0
   376
	TInt err;
sl@0
   377
	if ( (err=CreateBinFileForCard(aCardNum,&h))!=KErrNone )
sl@0
   378
		{
sl@0
   379
		delete cip;
sl@0
   380
		return(err);
sl@0
   381
		}
sl@0
   382
	cip->iWinHandle=h;
sl@0
   383
	iCardPool[aCardNum]=cip;
sl@0
   384
	return(KErrNone);
sl@0
   385
	}
sl@0
   386
sl@0
   387
void DWinsMMCStack::SetBusConfigDefaults(TMMCBusConfig& aConfig, TUint aClock)
sl@0
   388
//
sl@0
   389
// Fills BusConfig structure with default values
sl@0
   390
//
sl@0
   391
	{
sl@0
   392
	const TUint KWinsMaxHwInterfaceClk=104000;
sl@0
   393
	const TUint KWinsResponseTimeOut=6400;
sl@0
   394
	const TUint KWinsDataTimeOut=40000;
sl@0
   395
	const TUint KWinsBusyTimeOut=200000;
sl@0
   396
sl@0
   397
	aConfig.iBusClock = (aClock > KWinsMaxHwInterfaceClk) ? KWinsMaxHwInterfaceClk : aClock;
sl@0
   398
	aConfig.iResponseTimeOut=KWinsResponseTimeOut;
sl@0
   399
	aConfig.iDataTimeOut=KWinsDataTimeOut;
sl@0
   400
	aConfig.iBusyTimeOut=KWinsBusyTimeOut;
sl@0
   401
	}
sl@0
   402
sl@0
   403
void DWinsMMCStack::InitClockOff()
sl@0
   404
//
sl@0
   405
// Switch of the identification mode clock and enable the data transfer mode
sl@0
   406
// clock instead.
sl@0
   407
//
sl@0
   408
	{
sl@0
   409
	// empty.
sl@0
   410
	}
sl@0
   411
sl@0
   412
void DWinsMMCStack::ASSPReset()
sl@0
   413
//
sl@0
   414
// Stop all activities on the host stack
sl@0
   415
//
sl@0
   416
	{
sl@0
   417
	// empty.
sl@0
   418
	}
sl@0
   419
sl@0
   420
void DWinsMMCStack::ASSPDisengage()
sl@0
   421
//
sl@0
   422
// Forced release of all ASSP resources
sl@0
   423
//
sl@0
   424
	{
sl@0
   425
	}
sl@0
   426
sl@0
   427
void DWinsMMCStack::DoPowerDown()
sl@0
   428
//
sl@0
   429
// Power down the bus
sl@0
   430
//
sl@0
   431
	{
sl@0
   432
	// Change the state of all virtual cards present to Idle
sl@0
   433
	for (TInt i=0 ; i<TotalWinsMMC_CardSlots ; i++)
sl@0
   434
		iCardInfo[i]->iState=ECardStateIdle;
sl@0
   435
	}
sl@0
   436
sl@0
   437
sl@0
   438
LOCAL_C TInt SetMediaPasswordEnvironmentVar(TInt aSocketNum,TInt aCardNum,const TDesC8& aPasswd)
sl@0
   439
// 
sl@0
   440
// Set the password for local drive 'aLocalDrive', card number 'aCardNum' to 'aPasswd' - as an
sl@0
   441
// environment variable. Note that the card number is only relevant where the emulated drive
sl@0
   442
// supports card hot-swapping (i.e. F4 whilst F5 is held down).
sl@0
   443
//
sl@0
   444
	{
sl@0
   445
	// Setup the appropriate environment variable string '_EPOC_LocDrv_<locDrvNum>_PWORD_<cardNum>'
sl@0
   446
	TUint16 envVar[]=L"_EPOC_Socket_X_PWORD_Y";
sl@0
   447
sl@0
   448
	envVar[13]=(TUint16)('0'+aSocketNum);
sl@0
   449
	envVar[21]=(TUint16)('0'+aCardNum);
sl@0
   450
	
sl@0
   451
	// Setup the new value of the environment variable
sl@0
   452
	TUint16	envVal[100];
sl@0
   453
	TInt len=aPasswd.Length();
sl@0
   454
sl@0
   455
	// the password may be empty if a card's password is cleared
sl@0
   456
	if (len>(100-1))
sl@0
   457
		return(KErrArgument);
sl@0
   458
	memcpy(&envVal[0],reinterpret_cast<const TUint16 *>(aPasswd.Ptr()),len);
sl@0
   459
	envVal[len>>1]='\0';
sl@0
   460
sl@0
   461
	// Now set the new value for the environment variable
sl@0
   462
	if (SetEnvironmentVariable(envVar,&envVal[0]))
sl@0
   463
		return(KErrNone);
sl@0
   464
sl@0
   465
	return KErrGeneral;
sl@0
   466
	}
sl@0
   467
sl@0
   468
LOCAL_C TInt MediaPasswordEnvironmentVar(TInt aSocketNum,TInt aCardNum,TDes8& aPasswd)
sl@0
   469
// 
sl@0
   470
// Get the password for local drive 'aLocalDrive', card number 'aCardNum' into 'aPasswd' - from
sl@0
   471
// an environment variable. Note that the card number is only relevant where the emulated drive
sl@0
   472
// supports card hot-swapping (i.e. F4 whilst F5 is held down).
sl@0
   473
//
sl@0
   474
	{
sl@0
   475
	TUint16 envVar[]=L"_EPOC_Socket_X_PWORD_Y";
sl@0
   476
sl@0
   477
	envVar[13]=(TUint16)('0'+aSocketNum);
sl@0
   478
	envVar[21]=(TUint16)('0'+aCardNum);
sl@0
   479
	
sl@0
   480
	TUint16 envVal[100];	// To hold the value of the retreived environment variable
sl@0
   481
	
sl@0
   482
	DWORD len=GetEnvironmentVariable(envVar,&envVal[0],100);
sl@0
   483
	if (len>(TUint)100)
sl@0
   484
		return(KErrGeneral);
sl@0
   485
	if (len)
sl@0
   486
		{
sl@0
   487
		// Found the requested environment variable so there is a password for this local drive / card. 
sl@0
   488
		if ((len<<1)<=KMaxMediaPassword)
sl@0
   489
			{
sl@0
   490
			aPasswd.FillZ(KMaxMediaPassword);
sl@0
   491
			aPasswd.Zero();
sl@0
   492
			aPasswd.Copy(reinterpret_cast<TUint8*>(&envVal[0]),len<<1);
sl@0
   493
			return(KErrNone);	
sl@0
   494
			}
sl@0
   495
		else	
sl@0
   496
			return(KErrGeneral);	
sl@0
   497
		}
sl@0
   498
sl@0
   499
	return(KErrNotFound);
sl@0
   500
	}
sl@0
   501
sl@0
   502
TMMCErr DWinsMMCStack::DoPowerUpSM()
sl@0
   503
//
sl@0
   504
//	State Machine functions implemented in ASSP layer
sl@0
   505
//
sl@0
   506
	{
sl@0
   507
	enum states
sl@0
   508
		{
sl@0
   509
		EStBegin=0,
sl@0
   510
		EStEnd
sl@0
   511
		};
sl@0
   512
sl@0
   513
	SMF_BEGIN
sl@0
   514
sl@0
   515
	__KTRACE_OPT(KPBUS1, Kern::Printf("DoPowerUpSM: BEGIN"));
sl@0
   516
sl@0
   517
	if( MMCSocket()->iVcc->SetState(EPsuOnCurLimit) != KErrNone )
sl@0
   518
		return( KMMCErrHardware );
sl@0
   519
sl@0
   520
	for (TInt i=0 ; i<TotalWinsMMC_CardSlots ; i++)
sl@0
   521
		{
sl@0
   522
		// Attempt to retrieve a password for this card from environment settings (as long as this
sl@0
   523
		// isn't card0 and we are simulating this is not present)
sl@0
   524
		TInt cardNum=(i==0) ? *Wins::CurrentPBusDevicePtr() : i;
sl@0
   525
		if (cardNum>=0 && MediaPasswordEnvironmentVar(MMCSocket()->iSocketNumber,cardNum,*(iCardInfo[i]->iPWD))==KErrNone)
sl@0
   526
			{
sl@0
   527
			// Card has a password so lock it automatically on power up.		
sl@0
   528
			iCardInfo[i]->iIsLocked=(iCardInfo[i]->iPWD->Length() > 0);
sl@0
   529
			}
sl@0
   530
		else	
sl@0
   531
			iCardInfo[i]->iIsLocked=EFalse;
sl@0
   532
			
sl@0
   533
		iCardInfo[i]->iRCA=0x0001;		// Default RCA - spec 2.2, s4.2.1, 5.4
sl@0
   534
		}
sl@0
   535
sl@0
   536
		ReportPowerUp();
sl@0
   537
sl@0
   538
	SMF_END
sl@0
   539
	}
sl@0
   540
sl@0
   541
TMMCErr DWinsMMCStack::InitClockOnSM()
sl@0
   542
//
sl@0
   543
// Switch on the identification mode clock
sl@0
   544
//
sl@0
   545
	{
sl@0
   546
	enum states
sl@0
   547
		{
sl@0
   548
		EStBegin=0,
sl@0
   549
		EStEnd
sl@0
   550
		};
sl@0
   551
	SMF_BEGIN
sl@0
   552
sl@0
   553
	SMF_END
sl@0
   554
	}
sl@0
   555
sl@0
   556
TMMCErr DWinsMMCStack::ModifyCardCapabilitySM()
sl@0
   557
//
sl@0
   558
// This function provides a chance to modify the capability of paticular cards.
sl@0
   559
// Licensee may overide this function to modify certain card's capability as needed.
sl@0
   560
// A state machine is needed in derived function and function of base class should be
sl@0
   561
// called in order to act more generic behaviour.
sl@0
   562
//
sl@0
   563
    {
sl@0
   564
		enum states
sl@0
   565
			{
sl@0
   566
			EStBegin=0,
sl@0
   567
            EStDone,
sl@0
   568
			EStEnd
sl@0
   569
			};
sl@0
   570
sl@0
   571
    SMF_BEGIN
sl@0
   572
sl@0
   573
        SMF_INVOKES( DMMCStack::BaseModifyCardCapabilitySMST, EStDone )
sl@0
   574
sl@0
   575
    SMF_STATE(EStDone)
sl@0
   576
sl@0
   577
    SMF_END
sl@0
   578
    }
sl@0
   579
sl@0
   580
TInt DWinsMMCStack::GetTargetSlotNumber(TBool anRCASupplied,const TRCA& anRCA)
sl@0
   581
// 
sl@0
   582
// Attempt to determine the slot number of the target card. If the received command
sl@0
   583
// contained an RCA then 'anRCASupplied' will be ETrue - in which case, 'anRCA'
sl@0
   584
// contains the RCA in question.
sl@0
   585
// 
sl@0
   586
	{
sl@0
   587
	TInt selCardIdx = KBroadcastToAllCards;
sl@0
   588
sl@0
   589
	// if an RCA was supplied, then work out which card slot it corresponds to
sl@0
   590
	if (anRCASupplied)
sl@0
   591
		{
sl@0
   592
		for (TInt i = 0 ; i < TotalWinsMMC_CardSlots ; ++i)
sl@0
   593
			{
sl@0
   594
			if (iCardInfo[i]->iRCA==anRCA)
sl@0
   595
				{
sl@0
   596
				selCardIdx=i;
sl@0
   597
				break;
sl@0
   598
				}
sl@0
   599
			}
sl@0
   600
		}
sl@0
   601
	// else search for currently selected card
sl@0
   602
	else
sl@0
   603
		{
sl@0
   604
		for (TInt i = 0; i < TotalWinsMMC_CardSlots; ++i)
sl@0
   605
			{
sl@0
   606
			if (iCardInfo[i]->iState == ECardStateTran)
sl@0
   607
				{
sl@0
   608
				selCardIdx = i;
sl@0
   609
				break;
sl@0
   610
				}
sl@0
   611
			}
sl@0
   612
		}
sl@0
   613
sl@0
   614
	return(selCardIdx);
sl@0
   615
	}
sl@0
   616
sl@0
   617
TMMCErr DWinsMMCStack::IssueMMCCommandSM()
sl@0
   618
//
sl@0
   619
// Top level ASSP command executor
sl@0
   620
//
sl@0
   621
	{
sl@0
   622
	enum states
sl@0
   623
		{
sl@0
   624
		EStBegin=0,
sl@0
   625
		EStDoubleBuffer,
sl@0
   626
		EStCommandDone,
sl@0
   627
		EStEnd
sl@0
   628
		};
sl@0
   629
sl@0
   630
	TMMCCommandDesc& cmd = Command();
sl@0
   631
sl@0
   632
	TRCA tgtRCA=0;
sl@0
   633
	TBool supRCA=EFalse;
sl@0
   634
	// Record the RCA if it is embedded in the argument [31:16].
sl@0
   635
	if (cmd.iCommand == ECmdSetRelativeAddr	||	cmd.iCommand == ECmdSelectCard
sl@0
   636
	||	cmd.iCommand == ECmdSendCSD			||	cmd.iCommand == ECmdSendCID
sl@0
   637
	||	cmd.iCommand == ECmdSendStatus		||	cmd.iCommand == ECmdGoInactiveState
sl@0
   638
	||	cmd.iCommand == ECmdFastIO 			||  cmd.iCommand == ECmdAppCmd )
sl@0
   639
		{
sl@0
   640
		supRCA=ETrue;
sl@0
   641
		tgtRCA=TUint16(cmd.iArgument >> 16);
sl@0
   642
		}
sl@0
   643
sl@0
   644
	// Attempt to determine the target card using supplied RCA
sl@0
   645
	TInt selCardIdx=GetTargetSlotNumber(supRCA,tgtRCA);
sl@0
   646
	
sl@0
   647
	// Simulation of card swapping (i.e. F4/F5) is performed on slot 0. If this is currently
sl@0
   648
	// set to simulate no card present and the issued command is targetted specifically at the
sl@0
   649
	// card in slot 0 (i.e. not a broadcast command) then timeout.
sl@0
   650
	if (selCardIdx==0 && *Wins::CurrentPBusDevicePtr() < 0)
sl@0
   651
		return(KMMCErrResponseTimeOut);
sl@0
   652
	 
sl@0
   653
	// If an RCA was supplied but didn't coincide with the RCAs of any cards present 
sl@0
   654
	// then timeout (Ignore SET_RCA and APP_CMD as these are sent before RCAs are assigned).
sl@0
   655
	if (supRCA && selCardIdx==KBroadcastToAllCards &&
sl@0
   656
		cmd.iCommand != ECmdSetRelativeAddr && cmd.iCommand != ECmdAppCmd)
sl@0
   657
		return(KMMCErrResponseTimeOut);
sl@0
   658
sl@0
   659
	HANDLE winHandle=NULL;
sl@0
   660
sl@0
   661
	// CMD42 is a data transfer command.  That means the R1 response that it returns
sl@0
   662
	// immediately is the state it is in on receiving the data block, and not after
sl@0
   663
	// processing it.  If the data block is invalid then LOCK_UNLOCK_FAILED will be
sl@0
   664
	// set in the R1 response which is sent in reply to the next command.
sl@0
   665
sl@0
   666
	TBool nextCMD42Failed = EFalse;
sl@0
   667
	TBool lock_unlock_failed=EFalse;
sl@0
   668
sl@0
   669
	// When the card is locked, it will only respond to basic command class (0) and
sl@0
   670
	// lock card command class (7).  An exception is CMD16.  This is sent before CMD42,
sl@0
   671
	// but is classified (MMC Spec 23.2, table 5) as belonging to classes 2 and 4.
sl@0
   672
	// For data transfer commands, LOCK_UNLOCK_FAIL is set in response to the following
sl@0
   673
	const TMMCCommandEnum origCmd(cmd.iCommand);
sl@0
   674
	if (	selCardIdx != KBroadcastToAllCards
sl@0
   675
		&&	iCardInfo[selCardIdx]->iIsLocked			// If locked and not in CCC 0 or 7 then skip
sl@0
   676
		&&	(	((cmd.iSpec.iCommandClass & (KMMCCmdClassBasic | KMMCCmdClassLockCard)) == 0)
sl@0
   677
			&&	cmd.iCommand != ECmdSetBlockLen ) )
sl@0
   678
		{
sl@0
   679
		lock_unlock_failed = ETrue;				// try to access locked card
sl@0
   680
		cmd.iCommand = TMMCCommandEnum(-1);		// skip command processing
sl@0
   681
		}
sl@0
   682
sl@0
   683
	SMF_BEGIN
sl@0
   684
sl@0
   685
	TBool rto = EFalse;							// response timeout
sl@0
   686
	switch (cmd.iCommand)
sl@0
   687
		{
sl@0
   688
		case ECmdGoIdleState:	// CMD0
sl@0
   689
			{
sl@0
   690
			for (TInt i = 0; i < TotalWinsMMC_CardSlots; ++i)
sl@0
   691
				iCardInfo[i]->iState = ECardStateIdle;
sl@0
   692
			}
sl@0
   693
			break;
sl@0
   694
sl@0
   695
		case ECmdSendOpCond:	// CMD1
sl@0
   696
			{
sl@0
   697
			for (TInt i = 0; i < TotalWinsMMC_CardSlots; ++i)
sl@0
   698
				iCardInfo[i]->iState = ECardStateReady;
sl@0
   699
sl@0
   700
			// bit32 is set to indicate cards are not still powering up
sl@0
   701
			TUint32 r3 = KMMCWinsCardOCRValue | KMMCOCRBusy;
sl@0
   702
			TMMC::BigEndian4Bytes(cmd.iResponse, r3);
sl@0
   703
			}
sl@0
   704
			break;
sl@0
   705
sl@0
   706
		case ECmdAllSendCID:	// CMD2
sl@0
   707
			{
sl@0
   708
			TInt idx = FindAnyCardInStack(ECardStateReady);
sl@0
   709
sl@0
   710
			if (idx == -1)
sl@0
   711
				rto = ETrue;
sl@0
   712
			else
sl@0
   713
				{
sl@0
   714
				iCardInfo[idx]->iCID.Copy(cmd.iResponse);
sl@0
   715
				iCardInfo[idx]->iState = ECardStateIdent;
sl@0
   716
				}
sl@0
   717
			}
sl@0
   718
			break;
sl@0
   719
sl@0
   720
		case ECmdSetRelativeAddr:	// CMD3
sl@0
   721
			{
sl@0
   722
			TInt idx = FindOneCardInStack(ECardStateIdent);
sl@0
   723
			iCardInfo[idx]->iRCA = tgtRCA;
sl@0
   724
			iCardInfo[idx]->iState=ECardStateStby;
sl@0
   725
			selCardIdx = idx;					// set R1 response at end
sl@0
   726
			}
sl@0
   727
			break;
sl@0
   728
sl@0
   729
		case ECmdSelectCard:		// CMD7
sl@0
   730
			{
sl@0
   731
			// switch to broadcast mode so the currently selected and new cards
sl@0
   732
			// receive the command simultaneously.
sl@0
   733
sl@0
   734
			TInt idx = FindAnyCardInStack(ECardStateTran);
sl@0
   735
			if (idx != -1)
sl@0
   736
				iCardInfo[idx]->iState = ECardStateStby;
sl@0
   737
			iCardInfo[selCardIdx]->iState = ECardStateTran;
sl@0
   738
			}
sl@0
   739
			break;
sl@0
   740
sl@0
   741
		case ECmdSendStatus:
sl@0
   742
			// R1 response so status return as for any other R1 command.
sl@0
   743
			break;
sl@0
   744
sl@0
   745
		case ECmdReadSingleBlock:
sl@0
   746
		case ECmdReadMultipleBlock:
sl@0
   747
			{
sl@0
   748
			winHandle=iCardInfo[selCardIdx]->iWinHandle;
sl@0
   749
sl@0
   750
			if ( cmd.iSpec.iUseStopTransmission && cmd.iBlockLength >= cmd.iTotalLength)
sl@0
   751
				return( KMMCErrNotSupported );
sl@0
   752
sl@0
   753
    		TMMCErr err;
sl@0
   754
			TInt pos = cmd.iArgument;
sl@0
   755
    		if (SetFilePointer(winHandle,pos,NULL,FILE_BEGIN)==0xffffffffu)
sl@0
   756
        		err=MapLastErrorMmc();
sl@0
   757
    		else
sl@0
   758
        		{
sl@0
   759
				iBytesToTransfer = cmd.BufferLength();
sl@0
   760
				err = ReadWriteData(selCardIdx, cmd.iDataMemoryP, iBytesToTransfer, cmd.iSpec.iDirection);
sl@0
   761
				if(err == KMMCErrNone)
sl@0
   762
					{
sl@0
   763
					Session().RequestMoreData();
sl@0
   764
					SMF_WAITS(EStDoubleBuffer);
sl@0
   765
					}
sl@0
   766
				}
sl@0
   767
			if (err!=KMMCErrNone)
sl@0
   768
				return(err);
sl@0
   769
			}
sl@0
   770
			break;
sl@0
   771
sl@0
   772
		// ------------------------------------------------------------------
sl@0
   773
		case ECmdWriteBlock:
sl@0
   774
		case ECmdWriteMultipleBlock:
sl@0
   775
			{
sl@0
   776
			HANDLE h = iCardInfo[selCardIdx]->iWinHandle;
sl@0
   777
sl@0
   778
    		TMMCErr err;
sl@0
   779
			TInt pos = cmd.iArgument;
sl@0
   780
    		if (SetFilePointer(h, pos, NULL, FILE_BEGIN)==0xffffffffu)
sl@0
   781
        		err = MapLastErrorMmc();
sl@0
   782
    		else
sl@0
   783
        		{
sl@0
   784
				iBytesToTransfer = cmd.BufferLength();
sl@0
   785
				err = ReadWriteData(selCardIdx, cmd.iDataMemoryP, iBytesToTransfer, cmd.iSpec.iDirection);
sl@0
   786
				if(err == KMMCErrNone)
sl@0
   787
					{
sl@0
   788
					Session().RequestMoreData();
sl@0
   789
					SMF_WAITS(EStDoubleBuffer);
sl@0
   790
					}
sl@0
   791
				}
sl@0
   792
sl@0
   793
			if (err!=KMMCErrNone)
sl@0
   794
				return(err);
sl@0
   795
			}
sl@0
   796
			break;
sl@0
   797
sl@0
   798
		case ECmdAppCmd:
sl@0
   799
			rto = ETrue;
sl@0
   800
			break;
sl@0
   801
sl@0
   802
		case ECmdSendCSD:
sl@0
   803
			{
sl@0
   804
			iCardInfo[selCardIdx]->GetCSD(cmd.iResponse);
sl@0
   805
			break;
sl@0
   806
			}
sl@0
   807
sl@0
   808
		// ------------------------------------------------------------------
sl@0
   809
		case ECmdLockUnlock:
sl@0
   810
			// in EPOC, Lock() does not actually lock the card.  It just sets the
sl@0
   811
			// password.  This means that the card is still accessible to the user,
sl@0
   812
			// but must be unlocked the next time it is powered up.
sl@0
   813
sl@0
   814
			// a real card will transiently go into rcv and prg state while processing
sl@0
   815
			// this command.  When finished, it will fall back into tran state.
sl@0
   816
			// The R1 response is sent immediately after CMD42.  CIMReadWriteBlocksSM()
sl@0
   817
			// sends CMD13 to find out whether or not LOCK_UNLOCK_FAIL was set.
sl@0
   818
sl@0
   819
			// the asserts in this case protect against invalid data being sent from the
sl@0
   820
			// media driver.  A real card would fail these corrupt data blocks.
sl@0
   821
sl@0
   822
			{
sl@0
   823
#ifdef __CARD0_NOT_LOCKABLE__
sl@0
   824
			if (*Wins::CurrentPBusDevicePtr() == 0)
sl@0
   825
				return KMMCErrNotSupported;
sl@0
   826
#endif
sl@0
   827
#ifdef __CARD1_NOT_LOCKABLE__
sl@0
   828
			if (*Wins::CurrentPBusDevicePtr() == 1)
sl@0
   829
				return KMMCErrNotSupported;
sl@0
   830
#endif
sl@0
   831
			const TInt8 cmd_byte(*cmd.iDataMemoryP);
sl@0
   832
			__ASSERT_DEBUG(										// ensure not CLR_PWD && SET_PWD
sl@0
   833
				!((cmd_byte & KMMCLockUnlockClrPwd) && (cmd_byte & KMMCLockUnlockSetPwd)),
sl@0
   834
				DWinsMMCStack::Panic(DWinsMMCStack::EWinsMMCCorruptCommand) );
sl@0
   835
			
sl@0
   836
			__ASSERT_DEBUG(										// ensure not FORCE_ERASE with CLR_PWD or SET_PWD
sl@0
   837
				!((cmd_byte & KMMCLockUnlockErase) && (cmd_byte & (KMMCLockUnlockSetPwd | KMMCLockUnlockClrPwd))),
sl@0
   838
				DWinsMMCStack::Panic(DWinsMMCStack::EWinsMMCCorruptCommand) );
sl@0
   839
			
sl@0
   840
			__ASSERT_DEBUG(										// not actually lock a card while setting the password
sl@0
   841
				((cmd_byte & (KMMCLockUnlockLockUnlock | KMMCLockUnlockSetPwd)) != (KMMCLockUnlockLockUnlock | KMMCLockUnlockSetPwd)),
sl@0
   842
				DWinsMMCStack::Panic(DWinsMMCStack::EWinsMMCLockAttempt) );
sl@0
   843
sl@0
   844
			if (cmd_byte & KMMCLockUnlockErase)								// Forced Erase of a locked card
sl@0
   845
				{
sl@0
   846
				if (iCardInfo[selCardIdx]->iIsLocked)						// Forced erase when locked
sl@0
   847
					{
sl@0
   848
					iCardInfo[selCardIdx]->iPWD->Zero();					// Remove the password
sl@0
   849
					iCardInfo[selCardIdx]->iIsLocked = EFalse;
sl@0
   850
					nextCMD42Failed = EFalse;
sl@0
   851
					
sl@0
   852
					TInt cardNum = (selCardIdx==0) ? *Wins::CurrentPBusDevicePtr() : selCardIdx;
sl@0
   853
					SetMediaPasswordEnvironmentVar(MMCSocket()->iSocketNumber,cardNum,*(iCardInfo[selCardIdx]->iPWD));
sl@0
   854
sl@0
   855
					// Erase then entire contents of the emulated drive
sl@0
   856
					HANDLE handle = iCardInfo[selCardIdx]->iWinHandle;
sl@0
   857
					CloseHandle(handle);
sl@0
   858
					iCardInfo[selCardIdx]->iWinHandle = NULL;
sl@0
   859
					if(CreateBinFileForCard(selCardIdx, &handle, ETrue) != KErrNone)
sl@0
   860
						return(MapLastErrorMmc());
sl@0
   861
					iCardInfo[selCardIdx]->iWinHandle = handle;
sl@0
   862
					}
sl@0
   863
				else														// Forced erase when unlocked (illegal)
sl@0
   864
					{
sl@0
   865
					nextCMD42Failed = ETrue;
sl@0
   866
					}
sl@0
   867
				}
sl@0
   868
			else
sl@0
   869
				{
sl@0
   870
				const TInt8 pwd_len = *(cmd.iDataMemoryP + 1);
sl@0
   871
				const TPtrC8 pwd(cmd.iDataMemoryP + 2, pwd_len);
sl@0
   872
sl@0
   873
				if ((cmd_byte & KMMCLockUnlockClrPwd) != 0)			// CLR_PWD == 1
sl@0
   874
					{
sl@0
   875
					__ASSERT_DEBUG(
sl@0
   876
						pwd_len >= 0 && pwd_len <= KMaxMediaPassword,
sl@0
   877
						DWinsMMCStack::Panic(DWinsMMCStack::EWinsMMCCorruptCommand));
sl@0
   878
sl@0
   879
					if (iCardInfo[selCardIdx]->iIsLocked)						// clear when locked
sl@0
   880
						nextCMD42Failed = ETrue;
sl@0
   881
					else														// clear when unlocked
sl@0
   882
						{
sl@0
   883
						if (iCardInfo[selCardIdx]->iPWD->Compare(pwd) != 0)		// clear when unlocked with wrong password
sl@0
   884
							{
sl@0
   885
							nextCMD42Failed = ETrue;
sl@0
   886
							lock_unlock_failed = ETrue;
sl@0
   887
							}
sl@0
   888
						else													// clear when unlocked with right password
sl@0
   889
							{
sl@0
   890
							// Clear from password store 
sl@0
   891
							iCardInfo[selCardIdx]->iPWD->Zero();
sl@0
   892
							iCardInfo[selCardIdx]->iIsLocked = EFalse;
sl@0
   893
							nextCMD42Failed = EFalse;
sl@0
   894
							
sl@0
   895
							// Clear from environment settings
sl@0
   896
							TInt cardNum=(selCardIdx==0) ? *Wins::CurrentPBusDevicePtr() : selCardIdx; // Can't be -1 at this stage
sl@0
   897
							SetMediaPasswordEnvironmentVar(MMCSocket()->iSocketNumber,cardNum,*(iCardInfo[selCardIdx]->iPWD));
sl@0
   898
							}
sl@0
   899
						}
sl@0
   900
					}
sl@0
   901
				else if ((cmd_byte & KMMCLockUnlockSetPwd) == 0)	// SET_PWD == 0: unlock
sl@0
   902
					{
sl@0
   903
					__ASSERT_DEBUG(
sl@0
   904
						pwd_len >= 0 && pwd_len <= KMaxMediaPassword,
sl@0
   905
						DWinsMMCStack::Panic(DWinsMMCStack::EWinsMMCCorruptCommand) );
sl@0
   906
					
sl@0
   907
					if (! iCardInfo[selCardIdx]->iIsLocked)						// unlock when unlocked
sl@0
   908
						nextCMD42Failed = ETrue;
sl@0
   909
					else
sl@0
   910
						{
sl@0
   911
						if (iCardInfo[selCardIdx]->iPWD->Compare(pwd) != 0)		// unlock when locked with wrong password
sl@0
   912
							{
sl@0
   913
							nextCMD42Failed = ETrue;
sl@0
   914
							lock_unlock_failed = ETrue;
sl@0
   915
							}
sl@0
   916
						else													// unlock when locked with right password
sl@0
   917
							{
sl@0
   918
							iCardInfo[selCardIdx]->iIsLocked = EFalse;
sl@0
   919
							nextCMD42Failed = EFalse;
sl@0
   920
							}
sl@0
   921
						}
sl@0
   922
					}
sl@0
   923
				else  if ((cmd_byte & KMMCLockUnlockSetPwd) == KMMCLockUnlockSetPwd)	// SET_PWD == 1
sl@0
   924
					{
sl@0
   925
					__ASSERT_DEBUG(
sl@0
   926
						cmd_byte & KMMCLockUnlockSetPwd,
sl@0
   927
						DWinsMMCStack::Panic(DWinsMMCStack::EWinsMMCCorruptCommand) );
sl@0
   928
sl@0
   929
					// if pwd_len < iCardInfo[selCardIdx]->iPWD->Length() then data block must be invalid.
sl@0
   930
					// This can be caused by bad user input rather than inaccurate formation.
sl@0
   931
					if (!(	pwd_len >= iCardInfo[selCardIdx]->iPWD->Length()
sl@0
   932
						&&	pwd_len <= iCardInfo[selCardIdx]->iPWD->Length() + KMaxMediaPassword ))
sl@0
   933
						{
sl@0
   934
						nextCMD42Failed = ETrue;
sl@0
   935
						}
sl@0
   936
					else
sl@0
   937
						{
sl@0
   938
						TUint16 env_Var[]=L"_EPOC_PWD_LEN";
sl@0
   939
						TUint16 env_Val[2];
sl@0
   940
						TInt r=GetEnvironmentVariable(env_Var,&env_Val[0],2);
sl@0
   941
						r=r;//This code is added to suppress WINS warnings
sl@0
   942
						__ASSERT_DEBUG(r!=0,Kern::PanicCurrentThread(_L("PBUS-MMC-WINS-GETENV"),0));			
sl@0
   943
						const TInt old_pwd_len=env_Val[0]-1;
sl@0
   944
						TPtrC8 old_pwd(cmd.iDataMemoryP + 2, old_pwd_len);
sl@0
   945
						TPtrC8 new_pwd(cmd.iDataMemoryP + 2 + old_pwd_len, pwd_len - old_pwd_len);
sl@0
   946
						
sl@0
   947
						// card must not be locked and supplied current password must be correct
sl@0
   948
						if (iCardInfo[selCardIdx]->iIsLocked || iCardInfo[selCardIdx]->iPWD->Compare(old_pwd) != 0)
sl@0
   949
							{
sl@0
   950
							nextCMD42Failed = ETrue;
sl@0
   951
							lock_unlock_failed = ETrue;
sl@0
   952
							}
sl@0
   953
						else
sl@0
   954
							{
sl@0
   955
							// Set in password store
sl@0
   956
							iCardInfo[selCardIdx]->iPWD->Copy(new_pwd);
sl@0
   957
							nextCMD42Failed = EFalse;
sl@0
   958
							
sl@0
   959
							// Set in environment settings
sl@0
   960
							TInt cardNum=(selCardIdx==0) ? *Wins::CurrentPBusDevicePtr() : selCardIdx; // Can't be -1 at this stage
sl@0
   961
							SetMediaPasswordEnvironmentVar(MMCSocket()->iSocketNumber,cardNum,*(iCardInfo[selCardIdx]->iPWD));
sl@0
   962
							}
sl@0
   963
						}
sl@0
   964
					}
sl@0
   965
				else  if ((cmd_byte & KMMCLockUnlockLockUnlock) == KMMCLockUnlockLockUnlock)
sl@0
   966
					{
sl@0
   967
					__ASSERT_DEBUG(
sl@0
   968
						pwd_len >= 0 && pwd_len <= KMaxMediaPassword,
sl@0
   969
						DWinsMMCStack::Panic(DWinsMMCStack::EWinsMMCCorruptCommand) );
sl@0
   970
					
sl@0
   971
					if (iCardInfo[selCardIdx]->iIsLocked)						// lock when locked
sl@0
   972
						nextCMD42Failed = ETrue;
sl@0
   973
					else
sl@0
   974
						{
sl@0
   975
						if (iCardInfo[selCardIdx]->iPWD->Compare(pwd) != 0)		// lock with wrong password
sl@0
   976
							{
sl@0
   977
							nextCMD42Failed = ETrue;
sl@0
   978
							lock_unlock_failed = ETrue;
sl@0
   979
							}
sl@0
   980
						else													// lock with right password
sl@0
   981
							{
sl@0
   982
							iCardInfo[selCardIdx]->iIsLocked = ETrue;
sl@0
   983
							nextCMD42Failed = EFalse;
sl@0
   984
							}
sl@0
   985
						}
sl@0
   986
					}
sl@0
   987
				else
sl@0
   988
					{
sl@0
   989
					__ASSERT_DEBUG(EFalse, DWinsMMCStack::Panic(DWinsMMCStack::EWinsMMCLockAttempt) );
sl@0
   990
					}
sl@0
   991
				}
sl@0
   992
			}	// case ECmdLockUnlock
sl@0
   993
			break;
sl@0
   994
		
sl@0
   995
		case ECmdSetBlockCount:		
sl@0
   996
			{
sl@0
   997
			// Only supported in version 3.1
sl@0
   998
			if(Session().iCardP->CSD().SpecVers() != 3)
sl@0
   999
				{
sl@0
  1000
				return(KMMCErrNotSupported);
sl@0
  1001
				}
sl@0
  1002
			}
sl@0
  1003
			break;
sl@0
  1004
			
sl@0
  1005
		// ------------------------------------------------------------------
sl@0
  1006
		default:
sl@0
  1007
			break;
sl@0
  1008
		}
sl@0
  1009
sl@0
  1010
		if (rto)
sl@0
  1011
			{
sl@0
  1012
			return(KMMCErrResponseTimeOut);
sl@0
  1013
			}
sl@0
  1014
sl@0
  1015
	// drop through to command done...
sl@0
  1016
sl@0
  1017
	SMF_STATE(EStCommandDone)
sl@0
  1018
sl@0
  1019
		cmd.iCommand = origCmd;
sl@0
  1020
		// If this is an R1 or R1b response type command then return card status as a response
sl@0
  1021
		if (	selCardIdx != KBroadcastToAllCards
sl@0
  1022
			&&	(cmd.iSpec.iResponseType==ERespTypeR1 || cmd.iSpec.iResponseType==ERespTypeR1B) )
sl@0
  1023
			{
sl@0
  1024
			TUint32 resp(
sl@0
  1025
					iCardInfo[selCardIdx]->iState
sl@0
  1026
				|	((iCardInfo[selCardIdx]->iIsLocked ? 1 : 0) << 25)
sl@0
  1027
				|	((lock_unlock_failed ? 1 : 0) << 24) );
sl@0
  1028
sl@0
  1029
			if (iCMD42Failed)								// previous CMD42
sl@0
  1030
				{
sl@0
  1031
				resp |= KMMCStatErrLockUnlock;
sl@0
  1032
				nextCMD42Failed = EFalse;
sl@0
  1033
				}
sl@0
  1034
			iCMD42Failed = nextCMD42Failed;
sl@0
  1035
			TMMC::BigEndian4Bytes(&cmd.iResponse[0],resp); // Ignore bits 47-40
sl@0
  1036
			}
sl@0
  1037
sl@0
  1038
		SMF_GOTOS(EStEnd);
sl@0
  1039
sl@0
  1040
	SMF_STATE(EStDoubleBuffer)
sl@0
  1041
sl@0
  1042
		cmd.iBytesDone += iBytesToTransfer;
sl@0
  1043
sl@0
  1044
        if(cmd.iBytesDone < cmd.iTotalLength)
sl@0
  1045
			{
sl@0
  1046
			iBytesToTransfer = cmd.BufferLength();
sl@0
  1047
			TMMCErr err = ReadWriteData(selCardIdx, cmd.iDataMemoryP, iBytesToTransfer, cmd.iSpec.iDirection);
sl@0
  1048
			if(err == KMMCErrNone)
sl@0
  1049
				{
sl@0
  1050
				Session().RequestMoreData();
sl@0
  1051
				SMF_WAITS(EStDoubleBuffer);
sl@0
  1052
				}
sl@0
  1053
			else
sl@0
  1054
				{
sl@0
  1055
				return(err);
sl@0
  1056
				}
sl@0
  1057
			}
sl@0
  1058
		else
sl@0
  1059
			{
sl@0
  1060
			SMF_GOTOS(EStCommandDone);
sl@0
  1061
			}
sl@0
  1062
sl@0
  1063
	SMF_END
sl@0
  1064
	}
sl@0
  1065
sl@0
  1066
sl@0
  1067
TMMCErr DWinsMMCStack::ReadWriteData(TInt aCardIdx, TUint8* aDataP, TUint32 aLength, TMMCCmdDirEnum aDir)
sl@0
  1068
	{
sl@0
  1069
	TMMCErr err = KMMCErrNone;
sl@0
  1070
sl@0
  1071
	HANDLE h = iCardInfo[aCardIdx]->iWinHandle;
sl@0
  1072
sl@0
  1073
	DWORD res;
sl@0
  1074
	TBool success;
sl@0
  1075
	
sl@0
  1076
	if(aDir == EDirWrite)
sl@0
  1077
		{
sl@0
  1078
		success = WriteFile(h, (LPCVOID)aDataP, aLength, &res, NULL);
sl@0
  1079
		}
sl@0
  1080
	else
sl@0
  1081
		{
sl@0
  1082
		success = ReadFile(h, (LPVOID)aDataP, aLength, &res, NULL);
sl@0
  1083
		}
sl@0
  1084
sl@0
  1085
	if (!success)
sl@0
  1086
		{
sl@0
  1087
		err=MapLastErrorMmc();
sl@0
  1088
		}
sl@0
  1089
	else if (res != (DWORD)aLength)
sl@0
  1090
		{
sl@0
  1091
		err=KMMCErrGeneral;
sl@0
  1092
		}
sl@0
  1093
sl@0
  1094
	return(err);
sl@0
  1095
	}
sl@0
  1096
sl@0
  1097
sl@0
  1098
TInt DWinsMMCStack::FindAnyCardInStack(TMMCardStateEnum aState)
sl@0
  1099
//
sl@0
  1100
// first first active card in supplied state.  Return -1 if
sl@0
  1101
// no active card is in supplied state.
sl@0
  1102
//
sl@0
  1103
	{
sl@0
  1104
	for (TInt i = 0; i < TotalWinsMMC_CardSlots; ++i)
sl@0
  1105
		{
sl@0
  1106
		if (iCardInfo[i]->iState == aState)
sl@0
  1107
			return i;
sl@0
  1108
		}
sl@0
  1109
	return -1;
sl@0
  1110
	}
sl@0
  1111
sl@0
  1112
TInt DWinsMMCStack::FindFirstCardInStack(TMMCardStateEnum aState)
sl@0
  1113
//
sl@0
  1114
// find card which is active on bus and in supplied state.
sl@0
  1115
// There can be more than one active card in the the supplied state,
sl@0
  1116
// but there should be at least one.
sl@0
  1117
//
sl@0
  1118
	{
sl@0
  1119
	TInt idx = -1;
sl@0
  1120
	for (TInt i = 0; idx != -1 && i < TotalWinsMMC_CardSlots; ++i)
sl@0
  1121
		{
sl@0
  1122
		if (iCardInfo[i]->iState == aState)
sl@0
  1123
			idx = i;
sl@0
  1124
		}
sl@0
  1125
sl@0
  1126
	__ASSERT_DEBUG(idx != -1, DWinsMMCStack::Panic(DWinsMMCStack::EStkFFCNoneSel));
sl@0
  1127
	return idx;
sl@0
  1128
	}
sl@0
  1129
sl@0
  1130
TInt DWinsMMCStack::FindOneCardInStack(TMMCardStateEnum aState)
sl@0
  1131
//
sl@0
  1132
// find card which is active on bus and in supplied state.
sl@0
  1133
// There should be exactly one active card in the supplied state.
sl@0
  1134
//
sl@0
  1135
	{
sl@0
  1136
	TInt idx = -1;
sl@0
  1137
	for (TInt i = 0; i < TotalWinsMMC_CardSlots; ++i)
sl@0
  1138
		{
sl@0
  1139
		if (iCardInfo[i]->iState == aState)
sl@0
  1140
			{
sl@0
  1141
			__ASSERT_DEBUG(idx == -1, DWinsMMCStack::Panic(DWinsMMCStack::EStkFOCMultiSel));
sl@0
  1142
			idx = i;
sl@0
  1143
			}
sl@0
  1144
		}
sl@0
  1145
sl@0
  1146
	__ASSERT_DEBUG(idx != -1, DWinsMMCStack::Panic(DWinsMMCStack::EStkFOCNoneSel));
sl@0
  1147
	return idx;
sl@0
  1148
	}
sl@0
  1149
sl@0
  1150
void DWinsMMCStack::SetupDiskParms(TUint aDiskSize)
sl@0
  1151
	{	
sl@0
  1152
//
sl@0
  1153
//	setup parms for emulated mmc disk size
sl@0
  1154
//
sl@0
  1155
	// force a minimum of 32 KB total size
sl@0
  1156
	if (aDiskSize<32)
sl@0
  1157
		aDiskSize=32;
sl@0
  1158
	// first setup the CSD parameters
sl@0
  1159
	CSIZE_MULT = 0;
sl@0
  1160
	TUint newCSIZE = aDiskSize>>1;	// with zero multiplier 1 + size parameter = size in KB / 2
sl@0
  1161
	while((newCSIZE>0xfff)&&(CSIZE_MULT<7))	
sl@0
  1162
		// size parameter 12 bits, multiplier 3 bits
sl@0
  1163
		{
sl@0
  1164
		// size parameter too big and multiplier still has room to
sl@0
  1165
		// grow so increase multiplier and reduce size parameter
sl@0
  1166
		CSIZE_MULT++; 
sl@0
  1167
		newCSIZE = aDiskSize>>(1+CSIZE_MULT);
sl@0
  1168
		}
sl@0
  1169
	CSIZE = newCSIZE;
sl@0
  1170
	// as CSIZE = 1 + CSIZE
sl@0
  1171
	CSIZE--;
sl@0
  1172
	// restrict to 12 bits
sl@0
  1173
	if (CSIZE>0xfff)
sl@0
  1174
		CSIZE=0xfff;
sl@0
  1175
	// now setup TotalDiskSize
sl@0
  1176
	TotalMDiskSize = 512 * (1+CSIZE) * (1<<(2+CSIZE_MULT));
sl@0
  1177
	}
sl@0
  1178
sl@0
  1179
// ======== TWinsMMCMediaChange ========
sl@0
  1180
sl@0
  1181
#pragma warning( disable : 4355 )	// this used in initializer list
sl@0
  1182
DWinsMMCMediaChange::DWinsMMCMediaChange(TInt aMediaChangeNum)
sl@0
  1183
//
sl@0
  1184
// Constructor
sl@0
  1185
//
sl@0
  1186
	: DMMCMediaChange(aMediaChangeNum),
sl@0
  1187
	  iMediaChangeEnable(ETrue)
sl@0
  1188
	{
sl@0
  1189
sl@0
  1190
	iMediaDoorCloseReload=2; 	// Units: In theory-20ms, Actual-100ms
sl@0
  1191
	}
sl@0
  1192
#pragma warning( default : 4355 )
sl@0
  1193
sl@0
  1194
TInt DWinsMMCMediaChange::Create()
sl@0
  1195
//
sl@0
  1196
// Initialiser.
sl@0
  1197
//
sl@0
  1198
	{	
sl@0
  1199
	return(DMediaChangeBase::Create());
sl@0
  1200
	}
sl@0
  1201
sl@0
  1202
void DWinsMMCMediaChange::DoorOpenService()
sl@0
  1203
//
sl@0
  1204
// Handle the media change (this function, never postponed is called on media
sl@0
  1205
// change interrupt). 
sl@0
  1206
//
sl@0
  1207
	{
sl@0
  1208
	Disable();		// Disable interrupt until door closes again.
sl@0
  1209
	iDoorOpenDfc.Enque();
sl@0
  1210
	}
sl@0
  1211
sl@0
  1212
void DWinsMMCMediaChange::DoDoorOpen()
sl@0
  1213
//
sl@0
  1214
// Handle media door open (called on media door open interrupt). 
sl@0
  1215
//
sl@0
  1216
	{
sl@0
  1217
	iDoorClosedCount=iMediaDoorCloseReload;
sl@0
  1218
	// Just start a ticklink to poll for door closing
sl@0
  1219
	iTickLink.Periodic(KMediaChangeTickInterval,DWinsMMCMediaChange::Tick,this);
sl@0
  1220
    }
sl@0
  1221
sl@0
  1222
void DWinsMMCMediaChange::DoDoorClosed()
sl@0
  1223
//
sl@0
  1224
// Handle media door closing
sl@0
  1225
//
sl@0
  1226
	{
sl@0
  1227
	iTickLink.Cancel();	// Doesn't matter if wasn't enabled
sl@0
  1228
	Enable();	// Re-enable door interrupts
sl@0
  1229
sl@0
  1230
	// While the door was open the user may have changed the card in slot 0
sl@0
  1231
	if (iStackP && *Wins::CurrentPBusDevicePtr() >= 0)
sl@0
  1232
		iStackP->iCardInfo[0]=iStackP->iCardPool[*Wins::CurrentPBusDevicePtr()];
sl@0
  1233
	}
sl@0
  1234
sl@0
  1235
void DWinsMMCMediaChange::ForceMediaChange()
sl@0
  1236
//
sl@0
  1237
// Force media change
sl@0
  1238
//
sl@0
  1239
	{
sl@0
  1240
	DoorOpenService();
sl@0
  1241
	}
sl@0
  1242
sl@0
  1243
TMediaState DWinsMMCMediaChange::MediaState()
sl@0
  1244
//
sl@0
  1245
// Return status of media changed signal.
sl@0
  1246
//
sl@0
  1247
	{
sl@0
  1248
	if (iDoorClosedCount>0)
sl@0
  1249
		return(EDoorOpen);
sl@0
  1250
	return( (*Wins::MediaDoorOpenPtr())?EDoorOpen:EDoorClosed);
sl@0
  1251
	}
sl@0
  1252
sl@0
  1253
void DWinsMMCMediaChange::Tick(TAny *aPtr)
sl@0
  1254
//
sl@0
  1255
// Called on the tick to poll for door closing (called on DFC).
sl@0
  1256
//
sl@0
  1257
	{
sl@0
  1258
sl@0
  1259
	((DWinsMMCMediaChange*)aPtr)->TickService();
sl@0
  1260
	}
sl@0
  1261
sl@0
  1262
void DWinsMMCMediaChange::TickService()
sl@0
  1263
//
sl@0
  1264
// Called on the tick to poll for door closing (called on DFC).
sl@0
  1265
//
sl@0
  1266
	{
sl@0
  1267
sl@0
  1268
	__ASSERT_DEBUG(iDoorClosedCount>=0,DWinsMMCStack::Panic(DWinsMMCStack::EWinsMMCMediaChangeTickFault));
sl@0
  1269
sl@0
  1270
	if (!(*Wins::MediaDoorOpenPtr()))
sl@0
  1271
		{
sl@0
  1272
		if (iDoorClosedCount > 0)
sl@0
  1273
			{
sl@0
  1274
			if (--iDoorClosedCount == 0)
sl@0
  1275
				{
sl@0
  1276
				iTickLink.Cancel();		// cancel door closed timer
sl@0
  1277
				DoorClosedService();
sl@0
  1278
				}
sl@0
  1279
			}
sl@0
  1280
		}
sl@0
  1281
	else
sl@0
  1282
		iDoorClosedCount=iMediaDoorCloseReload; // Door open so start again.
sl@0
  1283
	}
sl@0
  1284
sl@0
  1285
void DWinsMMCMediaChange::Enable()
sl@0
  1286
//
sl@0
  1287
// Enable media change 
sl@0
  1288
//
sl@0
  1289
	{
sl@0
  1290
sl@0
  1291
	iMediaChangeEnable=ETrue;
sl@0
  1292
	}
sl@0
  1293
sl@0
  1294
void DWinsMMCMediaChange::Disable()
sl@0
  1295
//
sl@0
  1296
// Disable media change
sl@0
  1297
//
sl@0
  1298
	{
sl@0
  1299
sl@0
  1300
	iMediaChangeEnable=EFalse;
sl@0
  1301
	}
sl@0
  1302
sl@0
  1303
void DWinsMMCMediaChange::MediaChangeCallBack(TAny *aPtr)
sl@0
  1304
//
sl@0
  1305
// Static called on media change
sl@0
  1306
//
sl@0
  1307
	{
sl@0
  1308
	DWinsMMCMediaChange* mc=(DWinsMMCMediaChange*)aPtr;
sl@0
  1309
	if (mc!=NULL&&mc->iMediaChangeEnable)
sl@0
  1310
		mc->DoorOpenService();
sl@0
  1311
	}
sl@0
  1312
sl@0
  1313
// ======== TWinsCardInfo ========
sl@0
  1314
sl@0
  1315
void TWinsCardInfo::GetCSD(TUint8* aResp) const
sl@0
  1316
	{
sl@0
  1317
	// Bits 127-96
sl@0
  1318
	TUint32 csd=(KCsdStructure<<30); 	/* CSD_STRUCTURE */
sl@0
  1319
	csd|=		(KCsdSpecVers<<26); 	/* SPEC_VERS */
sl@0
  1320
	csd|=		(0x0E<<16);				/* TAAC: 1mS */  
sl@0
  1321
	csd|=		(0x0A<<8);				/* NSAC: 1000 */  
sl@0
  1322
	csd|=		(0x59);					/* TRAN_SPEED: 5.0Mbit/s */  
sl@0
  1323
	TMMC::BigEndian4Bytes(&aResp[0],csd);
sl@0
  1324
sl@0
  1325
	// Bits 95-64
sl@0
  1326
	TUint32 lockBit = KMMCCmdClassLockCard;
sl@0
  1327
#ifdef __CARD0_NOT_LOCKABLE__
sl@0
  1328
	if (*Wins::CurrentPBusDevicePtr() == 0)
sl@0
  1329
		lockBit = 0;
sl@0
  1330
#endif
sl@0
  1331
#ifdef __CARD1_NOT_LOCKABLE__
sl@0
  1332
	if (*Wins::CurrentPBusDevicePtr() == 1)
sl@0
  1333
		lockBit = 0;
sl@0
  1334
#endif
sl@0
  1335
	const TUint32 ccc = 
sl@0
  1336
			KMMCCmdClassBasic | KMMCCmdClassBlockRead
sl@0
  1337
		|	KMMCCmdClassBlockWrite | lockBit;
sl@0
  1338
	csd=		(ccc<<20); 	/* CCC: classes 0, 2, 4, and 7 */
sl@0
  1339
	csd|=		(0x9<<16); 	/* READ_BL_LEN: 512 bytes */
sl@0
  1340
	csd|=		(0x0<<15);	/* READ_BL_PARTIAL: No */  
sl@0
  1341
	csd|=		(0x0<<14);	/* WRITE_BLK_MISALIGN: No */  
sl@0
  1342
	csd|=		(0x0<<13);	/* READ_BLK_MISALIGN: No */  
sl@0
  1343
	csd|=		(0x0<<12);	/* DSR_IMP: No DSR */ 
sl@0
  1344
	csd|=		((DWinsMMCStack::CSIZE>>10&3)<<8);			/* C_SIZE: MMCSz Kb */
sl@0
  1345
	csd|=		((DWinsMMCStack::CSIZE>>2) & 0xFF);			/* C_SIZE: MMCSz Kb */
sl@0
  1346
	TMMC::BigEndian4Bytes(&aResp[4],csd); 
sl@0
  1347
	// Bits 63-32
sl@0
  1348
	csd=		((DWinsMMCStack::CSIZE&3)<<30); 			/* C_SIZE: MMCSz Kb */
sl@0
  1349
	csd|=		(0x1<<27); 	/* VDD_R_CURR_MIN: 1mA */
sl@0
  1350
	csd|=		(0x1<<24);	/* VDD_R_CURR_MAX: 5mA */  
sl@0
  1351
	csd|=		(0x2<<21); 	/* VDD_W_CURR_MIN: 5mA */
sl@0
  1352
	csd|=		(0x3<<18);	/* VDD_W_CURR_MAX: 25mA */  
sl@0
  1353
	csd|=		((DWinsMMCStack::CSIZE_MULT&0x07)<<15);		/* C_SIZE_MULT: 0 */  
sl@0
  1354
	csd|=		(0x0<<10);	/* SECTOR_SIZE: 1 write block */  
sl@0
  1355
	csd|=		(0x0<<5);	/* ERASE_GRP_SIZE: 1 secotr */  
sl@0
  1356
	csd|=		(0x0);		/* WP_GRP_SIZE: 1 erase group */  
sl@0
  1357
	TMMC::BigEndian4Bytes(&aResp[8],csd); 
sl@0
  1358
	// Bits 31-0
sl@0
  1359
	csd=		(0x0<<31); 	/* WP_GRP_ENABLE: No */
sl@0
  1360
	csd|=		(0x0<<29); 	/* DEFAULT_ECC: ? */
sl@0
  1361
	csd|=		(0x3<<26);	/* R2W_FACTOR: 8 */  
sl@0
  1362
	csd|=		(0x9<<22); 	/* WRITE_BL_LEN: 512 bytes */
sl@0
  1363
	csd|=		(0x0<<21);	/* WRITE_BL_PARTIAL: No */  
sl@0
  1364
	csd|=		(0x0<<15);	/* FILE_FORMAT_GRP: Hard disk */  
sl@0
  1365
	csd|=		(0x0<<14);	/* COPY: original */  
sl@0
  1366
	csd|=		(0x0<<13);	/* PERM_WRITE_PROTECT: No */  
sl@0
  1367
	csd|=		(0x0<<12);	/* TMP_WRITE_PROTECT: No */  
sl@0
  1368
	csd|=		(0x0<<10);	/* FILE_FORMAT: Hard disk */  
sl@0
  1369
	csd|=		(0x0<<8);	/* ECC: None */  
sl@0
  1370
	csd|=		(0x0<<1);	/* CRC: ? */  
sl@0
  1371
	csd|=		(0x1);		/* not used */  
sl@0
  1372
	TMMC::BigEndian4Bytes(&aResp[12],csd);
sl@0
  1373
	}
sl@0
  1374
sl@0
  1375
// ======== TWinsMMCPsu ========
sl@0
  1376
sl@0
  1377
sl@0
  1378
DWinsMMCPsu::DWinsMMCPsu(TInt aVccNum, TInt aMcId)
sl@0
  1379
//
sl@0
  1380
// Constructor.
sl@0
  1381
//
sl@0
  1382
	: DMMCPsu(aVccNum, aMcId)
sl@0
  1383
	{}
sl@0
  1384
sl@0
  1385
TInt DWinsMMCPsu::DoCreate()
sl@0
  1386
//
sl@0
  1387
// Initialise the PSU
sl@0
  1388
//
sl@0
  1389
    {
sl@0
  1390
	// Nothing to do
sl@0
  1391
	return KErrNone;
sl@0
  1392
    }
sl@0
  1393
sl@0
  1394
void DWinsMMCPsu::DoSetState(TPBusPsuState aState)
sl@0
  1395
//
sl@0
  1396
// Turn on/off the PSU. If it is possible to adjust the output voltage on this
sl@0
  1397
// PSU then retreive the required voltage level from TMMCPsu::iVoltageSetting
sl@0
  1398
// (which is in OCR register format).
sl@0
  1399
//
sl@0
  1400
    {
sl@0
  1401
sl@0
  1402
    switch (aState)
sl@0
  1403
        {
sl@0
  1404
        case EPsuOff:
sl@0
  1405
            break;
sl@0
  1406
        case EPsuOnFull:
sl@0
  1407
            break;
sl@0
  1408
        case EPsuOnCurLimit:
sl@0
  1409
            break;
sl@0
  1410
        }
sl@0
  1411
    }
sl@0
  1412
sl@0
  1413
TInt DWinsMMCPsu::VoltageInMilliVolts()
sl@0
  1414
//
sl@0
  1415
// Return the level of the PSU (in mV) or -ve if error.
sl@0
  1416
//
sl@0
  1417
    {
sl@0
  1418
sl@0
  1419
    return(0);
sl@0
  1420
    }
sl@0
  1421
sl@0
  1422
void DWinsMMCPsu::DoCheckVoltage()
sl@0
  1423
//
sl@0
  1424
// Check the voltage level of the PSU is as expected. Returns either KErrNone, KErrGeneral 
sl@0
  1425
// to indicate the pass/fail state or KErrNotReady if the voltage check isn't complete.
sl@0
  1426
//
sl@0
  1427
    {
sl@0
  1428
	ReceiveVoltageCheckResult(KErrNone);
sl@0
  1429
    }
sl@0
  1430
sl@0
  1431
void DWinsMMCPsu::PsuInfo(TPBusPsuInfo &anInfo)
sl@0
  1432
//
sl@0
  1433
// Return machine info relating to the MMC PSU supply
sl@0
  1434
//
sl@0
  1435
    {
sl@0
  1436
sl@0
  1437
	anInfo.iVoltageSupported=0x00040000; // 3.0V (OCR reg. format).
sl@0
  1438
	anInfo.iMaxCurrentInMicroAmps=0;
sl@0
  1439
	anInfo.iVoltCheckInterval=0;
sl@0
  1440
	anInfo.iVoltCheckMethod=EPsuChkComparator;
sl@0
  1441
	anInfo.iNotLockedTimeOut=0;
sl@0
  1442
	anInfo.iInactivityTimeOut=5;
sl@0
  1443
    }
sl@0
  1444