os/boardsupport/emulator/emulatorbsp/specific/sdcard/sdcard3c/sdio/pp_sdio.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
// Copyright (c) 2003-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_sdio.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
// ======== Register Map ========
sl@0
    26
sl@0
    27
typedef TInt (*TAccessFunction)(TInt aTargetCard, TInt aVal, TAny* aThis, TBool aRead, TUint8& aData);
sl@0
    28
sl@0
    29
const TInt KIoMapEnd = 0xFFFFFFFF;
sl@0
    30
sl@0
    31
struct SRegisterMapInfo
sl@0
    32
	{
sl@0
    33
public:
sl@0
    34
	TUint32 iRegisterID;				// Unique ID
sl@0
    35
	
sl@0
    36
	const SRegisterMapInfo* iChildMapP; // Pointer to child register map
sl@0
    37
	
sl@0
    38
	TUint32 iAddress;					// Start Address
sl@0
    39
	TUint32 iLength;					// Register Length in Bytes
sl@0
    40
	
sl@0
    41
	const TAny*	iDataP;					// Data for auto-access (may be NULL)
sl@0
    42
	TAccessFunction iAccessFunction;	// Invoked when register is accessed
sl@0
    43
	
sl@0
    44
	TUint8 iFlags;						// Bitmap of RO(0), R/W(1) bits (8-bit only?)
sl@0
    45
	};
sl@0
    46
sl@0
    47
// ======== Card Information Structures =========
sl@0
    48
sl@0
    49
sl@0
    50
sl@0
    51
const TUint32 KCommonCisPtr = 0x1010;
sl@0
    52
const TUint32 KCommonCisLen = 0x70;
sl@0
    53
sl@0
    54
LOCAL_D const TText8 CardCommonCis[KCommonCisLen] =
sl@0
    55
	{
sl@0
    56
//	0x20,0x04,0xc0,0x12,0x00,0x00,0x21,0x02,0x0c,0x00,0x22,0x06,0x00,0x00,0x01,0x32,
sl@0
    57
//	0x00,0x00,0x91,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x15,0x32,0x01,0x00,0x48,0x41,
sl@0
    58
//	0x47,0x49,0x57,0x41,0x52,0x41,0x20,0x53,0x59,0x53,0x2d,0x43,0x4f,0x4d,0x20,0x43,
sl@0
    59
//	0x4f,0x2e,0x2c,0x4c,0x54,0x44,0x2e,0x00,0x48,0x53,0x2d,0x53,0x44,0x44,0x4b,0x2d,
sl@0
    60
//	0x30,0x30,0x32,0x20,0x56,0x65,0x72,0x2e,0x50,0x61,0x6e,0x61,0x00,0x00,0xff,0xff,
sl@0
    61
//	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
sl@0
    62
//	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
sl@0
    63
sl@0
    64
	0x20,0x04,0xc0,0x12,0x00,0x00,0x21,0x02,0x0c,0x00,0x22,0x04,0x00,0x00,0x01,0x2A/*79*/,
sl@0
    65
	0x91,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x15,0x35,0x01,0x00,0x48,0x41,0x47,0x49,
sl@0
    66
	0x57,0x41,0x52,0x41,0x20,0x53,0x59,0x53,0x2d,0x43,0x4f,0x4d,0x20,0x43,0x4f,0x2e,
sl@0
    67
	0x2c,0x4c,0x54,0x44,0x2e,0x00,0x48,0x53,0x2d,0x53,0x44,0x44,0x4b,0x2d,0x30,0x30,
sl@0
    68
	0x32,0x20,0x56,0x65,0x72,0x2e,0x50,0x61,0x6e,0x61,0x00,0x53,0x48,0x50,0x00,0xff,
sl@0
    69
	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
sl@0
    70
	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
sl@0
    71
	};
sl@0
    72
sl@0
    73
const TUint32 KFn1CisPtr = 0x2000;
sl@0
    74
const TUint32 KFn1CisLen = 0x40;
sl@0
    75
sl@0
    76
LOCAL_D const TText8 Fn1Cis[KFn1CisLen] =
sl@0
    77
	{
sl@0
    78
	0x21,0x02,0x0c,0x00,0x22,0x24,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,
sl@0
    79
	0x00,0x03,0x00,0x02,0x00,0x00,0x3c,0x00,0x00,0x00,0xc8,0x00,0x00,0x00,0x00,0x00,
sl@0
    80
	0x00,0x00,0x00,0x00,0x2c,0x01,0xf4,0x01,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,
sl@0
    81
	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0xff,
sl@0
    82
	};
sl@0
    83
sl@0
    84
const TUint32 KFn2CisPtr = 0x3000;
sl@0
    85
const TUint32 KFn2CisLen = 0x40;
sl@0
    86
sl@0
    87
LOCAL_D const TText8 Fn2Cis[KFn2CisLen] =
sl@0
    88
	{
sl@0
    89
	0x21,0x02,0x0c,0x00,0x22,0x24,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,
sl@0
    90
	0x00,0x03,0x40,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,0xc8,0x00,0x00,0x00,0x00,0x00,
sl@0
    91
	0x00,0x00,0x00,0x00,0xfa,0x00,0xc2,0x01,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,
sl@0
    92
	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
sl@0
    93
	};
sl@0
    94
sl@0
    95
sl@0
    96
// ======== Card Common Control Registers =========
sl@0
    97
sl@0
    98
TUint8 GCCCRRegSdioRevision			= 0x00;
sl@0
    99
TUint8 GCCCRRegSdSpec				= 0x00;
sl@0
   100
TUint8 GCCCRRegIoEnable				= 0x00;
sl@0
   101
TUint8 GCCCRRegIoReady				= 0x00;
sl@0
   102
TUint8 GCCCRRegIntEnable			= 0x00;
sl@0
   103
TUint8 GCCCRRegIntPending			= 0x00;
sl@0
   104
TUint8 GCCCRRegIoAbort				= 0x00;
sl@0
   105
TUint8 GCCCRRegBusInterfaceControl	= 0x00;
sl@0
   106
TUint8 GCCCRRegCardCapability		= 0x00;
sl@0
   107
TUint8 GCCCRRegCisPtrLo				= (KCommonCisPtr & 0x0000FF);
sl@0
   108
TUint8 GCCCRRegCisPtrMid			= (KCommonCisPtr & 0x00FF00) >> 8;
sl@0
   109
TUint8 GCCCRRegCisPtrHi				= (KCommonCisPtr & 0xFF0000) >> 16;
sl@0
   110
TUint8 GCCCRRegBusSuspend			= 0x00;
sl@0
   111
TUint8 GCCCRRegFunctionSelect		= 0x00;
sl@0
   112
TUint8 GCCCRRegExecFlags			= 0x00;
sl@0
   113
TUint8 GCCCRRegReadyFlags			= 0x00;
sl@0
   114
TUint8 GCCCRRegFN0BlockSizeLo		= 0x00;	// Initialises with 0x0000
sl@0
   115
TUint8 GCCCRRegFN0BlockSizeHi		= 0x00;	// Initialises with 0x0000
sl@0
   116
sl@0
   117
TUint8 GFunctionToEnable = 0x00;
sl@0
   118
sl@0
   119
LOCAL_D const SRegisterMapInfo IoMapCCCR[] =
sl@0
   120
	{
sl@0
   121
		{KCCCRRegSdioRevision,		  NULL, 0x00, 0x01, &GCCCRRegSdioRevision,		  NULL, 0x00},
sl@0
   122
		{KCCCRRegSdSpec,			  NULL, 0x01, 0x01, &GCCCRRegSdSpec,			  NULL, 0x00},
sl@0
   123
		
sl@0
   124
		{KCCCRRegIoEnable,			  NULL, 0x02, 0x01, NULL, DWinsSDIOStack::AccessIoEnable, 0x00},
sl@0
   125
		
sl@0
   126
		{KCCCRRegIoReady,			  NULL, 0x03, 0x01, &GCCCRRegIoReady,			  NULL, 0x00},
sl@0
   127
		{KCCCRRegIntEnable,			  NULL, 0x04, 0x01, &GCCCRRegIntEnable,			  NULL, 0xFF},
sl@0
   128
		{KCCCRRegIntPending,		  NULL, 0x05, 0x01, &GCCCRRegIntPending,		  NULL, 0x00},
sl@0
   129
		{KCCCRRegIoAbort,			  NULL, 0x06, 0x01, &GCCCRRegIoAbort,			  NULL, 0xFF},
sl@0
   130
		{KCCCRRegBusInterfaceControl, NULL, 0x07, 0x01, &GCCCRRegBusInterfaceControl, NULL, 0xFF},
sl@0
   131
		{KCCCRRegCardCapability,	  NULL, 0x08, 0x01, &GCCCRRegCardCapability,	  NULL, 0x00},
sl@0
   132
		{KCCCRRegCisPtrLo,			  NULL, 0x09, 0x01, &GCCCRRegCisPtrLo,			  NULL, 0x00},
sl@0
   133
		{KCCCRRegCisPtrMid,			  NULL, 0x0a, 0x01, &GCCCRRegCisPtrMid,			  NULL, 0x00},
sl@0
   134
		{KCCCRRegCisPtrHi,			  NULL, 0x0b, 0x01, &GCCCRRegCisPtrHi,			  NULL, 0x00},
sl@0
   135
		{KCCCRRegBusSuspend,		  NULL, 0x0c, 0x01, &GCCCRRegBusSuspend,		  NULL, 0xFF},
sl@0
   136
		{KCCCRRegFunctionSelect,	  NULL, 0x0d, 0x01, &GCCCRRegFunctionSelect,	  NULL, 0xFF},
sl@0
   137
		{KCCCRRegExecFlags,			  NULL, 0x0e, 0x01, &GCCCRRegExecFlags,			  NULL, 0x00},
sl@0
   138
		{KCCCRRegReadyFlags,		  NULL, 0x0f, 0x01, &GCCCRRegReadyFlags,		  NULL, 0x00},
sl@0
   139
		{KCCCRRegFN0BlockSizeLo,	  NULL, 0x10, 0x01, &GCCCRRegFN0BlockSizeLo,	  NULL, 0x00},
sl@0
   140
		{KCCCRRegFN0BlockSizeHi,	  NULL, 0x11, 0x01, &GCCCRRegFN0BlockSizeHi,	  NULL, 0x00},
sl@0
   141
		{KIoMapEnd,					  NULL, 0,	  0,	NULL,						  NULL, 0xFF}
sl@0
   142
	};
sl@0
   143
sl@0
   144
sl@0
   145
// ======== Function Basic Register 1 =========
sl@0
   146
sl@0
   147
TUint8 GFBR1RegInterfaceCode = KFBRRegSupportsCSA;
sl@0
   148
TUint8 GFBR1RegExtendedCode  = 0x00;
sl@0
   149
TUint8 GFBR1RegPowerFlags	 = 0x00;
sl@0
   150
TUint8 GFBR1RegCisPtrLo		 = (KFn1CisPtr & 0x0000FF);
sl@0
   151
TUint8 GFBR1RegCisPtrMid	 = (KFn1CisPtr & 0x00FF00) >> 8;
sl@0
   152
TUint8 GFBR1RegCisPtrHi		 = (KFn1CisPtr & 0xFF0000) >> 16;
sl@0
   153
TUint8 GFBR1RegIoBlockSizeLo = 0x00;
sl@0
   154
TUint8 GFBR1RegIoBlockSizeHi = 0x00;
sl@0
   155
sl@0
   156
TUint32 GFBR1RegCsaPtr = 0x00000000;
sl@0
   157
sl@0
   158
LOCAL_D const SRegisterMapInfo IoMapFBR1[] =
sl@0
   159
	{
sl@0
   160
		{KFBRRegInterfaceCode, NULL, 0x100, 0x01, &GFBR1RegInterfaceCode, NULL, 0x00},
sl@0
   161
		{KFBRRegExtendedCode,  NULL, 0x101, 0x01, &GFBR1RegExtendedCode,  NULL, 0x00},
sl@0
   162
		{KFBRRegPowerFlags,	   NULL, 0x102, 0x01, &GFBR1RegPowerFlags,	  NULL, 0x00},
sl@0
   163
		{KFBRRegCisPtrLo,	   NULL, 0x109, 0x01, &GFBR1RegCisPtrLo,	  NULL, 0x00},
sl@0
   164
		{KFBRRegCisPtrMid,	   NULL, 0x10a, 0x01, &GFBR1RegCisPtrMid,	  NULL, 0x00},
sl@0
   165
		{KFBRRegCisPtrHi,	   NULL, 0x10b, 0x01, &GFBR1RegCisPtrHi,	  NULL, 0x00},
sl@0
   166
sl@0
   167
		{KFBRRegCsaPtrLo,	   NULL, 0x10c, 0x01, NULL, DWinsSDIOStack::AccessCsaPointer, 0xFF},
sl@0
   168
		{KFBRRegCsaPtrMid,	   NULL, 0x10d, 0x01, NULL, DWinsSDIOStack::AccessCsaPointer, 0xFF},
sl@0
   169
		{KFBRRegCsaPtrHi,	   NULL, 0x10e, 0x01, NULL, DWinsSDIOStack::AccessCsaPointer, 0xFF},
sl@0
   170
		{KFBRRegCsaWindow,	   NULL, 0x10f, 0x01, NULL, DWinsSDIOStack::AccessCsaWindow,  0xFF},
sl@0
   171
		
sl@0
   172
		{KFBRRegIoBlockSizeLo, NULL, 0x110, 0x01, &GFBR1RegIoBlockSizeLo, NULL, 0xFF},
sl@0
   173
		{KFBRRegIoBlockSizeHi, NULL, 0x111, 0x01, &GFBR1RegIoBlockSizeHi, NULL, 0xFF},
sl@0
   174
		{KIoMapEnd,			   NULL, 0,	    0,	  NULL,					  NULL, 0x00}
sl@0
   175
	};
sl@0
   176
sl@0
   177
// ======== Function Basic Register 2 ========
sl@0
   178
sl@0
   179
TUint8 GFBR2RegInterfaceCode = KFBRRegSupportsCSA | ESdioFunctionTypeUART;
sl@0
   180
TUint8 GFBR2RegExtendedCode  = 0x00;
sl@0
   181
TUint8 GFBR2RegPowerFlags	 = 0x00;
sl@0
   182
TUint8 GFBR2RegCisPtrLo		 = (KFn2CisPtr & 0x0000FF);
sl@0
   183
TUint8 GFBR2RegCisPtrMid	 = (KFn2CisPtr & 0x00FF00) >> 8;
sl@0
   184
TUint8 GFBR2RegCisPtrHi		 = (KFn2CisPtr & 0xFF0000) >> 16;
sl@0
   185
TUint8 GFBR2RegIoBlockSizeLo = 0x00;
sl@0
   186
TUint8 GFBR2RegIoBlockSizeHi = 0x00;
sl@0
   187
sl@0
   188
TUint32 GFBR2RegCsaPtr = 0x00000000;
sl@0
   189
sl@0
   190
LOCAL_D const SRegisterMapInfo IoMapFBR2[] =
sl@0
   191
	{
sl@0
   192
		{KFBRRegInterfaceCode, NULL, 0x200, 0x01, &GFBR2RegInterfaceCode, NULL, 0x00},
sl@0
   193
		{KFBRRegExtendedCode,  NULL, 0x201, 0x01, &GFBR2RegExtendedCode,  NULL, 0x00},
sl@0
   194
		{KFBRRegPowerFlags,	   NULL, 0x202, 0x01, &GFBR2RegPowerFlags,	  NULL, 0x00},
sl@0
   195
		{KFBRRegCisPtrLo,	   NULL, 0x209, 0x01, &GFBR2RegCisPtrLo,	  NULL, 0x00},
sl@0
   196
		{KFBRRegCisPtrMid,	   NULL, 0x20a, 0x01, &GFBR2RegCisPtrMid,	  NULL, 0x00},
sl@0
   197
		{KFBRRegCisPtrHi,	   NULL, 0x20b, 0x01, &GFBR2RegCisPtrHi,	  NULL, 0x00},
sl@0
   198
sl@0
   199
		{KFBRRegCsaPtrLo,	   NULL, 0x20c, 0x01, NULL, DWinsSDIOStack::AccessCsaPointer, 0xFF},
sl@0
   200
		{KFBRRegCsaPtrMid,	   NULL, 0x20d, 0x01, NULL, DWinsSDIOStack::AccessCsaPointer, 0xFF},
sl@0
   201
		{KFBRRegCsaPtrHi,	   NULL, 0x20e, 0x01, NULL, DWinsSDIOStack::AccessCsaPointer, 0xFF},
sl@0
   202
		{KFBRRegCsaWindow,	   NULL, 0x20f, 0x01, NULL, DWinsSDIOStack::AccessCsaWindow,  0xFF},
sl@0
   203
		
sl@0
   204
		{KFBRRegIoBlockSizeLo, NULL, 0x210, 0x01, &GFBR2RegIoBlockSizeLo, NULL, 0xFF},
sl@0
   205
		{KFBRRegIoBlockSizeHi, NULL, 0x211, 0x01, &GFBR2RegIoBlockSizeHi, NULL, 0xFF},
sl@0
   206
		{KIoMapEnd,			   NULL, 0,	    0,	  NULL,					  NULL, 0x00}
sl@0
   207
	};
sl@0
   208
sl@0
   209
// ======== Function Basic Register 1 =========
sl@0
   210
sl@0
   211
const TInt KIoMapCCCR	   = 0;
sl@0
   212
const TInt KIoMapFBR1	   = 1;
sl@0
   213
const TInt KIoMapFBR2	   = 2;
sl@0
   214
const TInt KIoMapCommonCis = 3;
sl@0
   215
const TInt KIoMapFn1Cis	   = 4;
sl@0
   216
const TInt KIoMapFn2Cis	   = 5;
sl@0
   217
sl@0
   218
LOCAL_D const SRegisterMapInfo IoMapTop[] =
sl@0
   219
	{
sl@0
   220
		{KIoMapCCCR,	  IoMapCCCR, 0x00,			0xFF,		   NULL,		  NULL, 0x00},
sl@0
   221
		{KIoMapFBR1,	  IoMapFBR1, 0x100,			0xFF,		   NULL,		  NULL, 0x00},		
sl@0
   222
		{KIoMapFBR2,	  IoMapFBR2, 0x200,			0xFF,		   NULL,		  NULL, 0x00},
sl@0
   223
		{KIoMapCommonCis, NULL,		 KCommonCisPtr, KCommonCisLen, CardCommonCis, NULL, 0x00},
sl@0
   224
		{KIoMapFn1Cis,	  NULL,		 KFn1CisPtr,	KFn1CisLen,	   Fn1Cis,		  NULL, 0x00},
sl@0
   225
		{KIoMapFn2Cis,	  NULL,		 KFn2CisPtr,	KFn2CisLen,	   Fn2Cis,		  NULL, 0x00},
sl@0
   226
		{KIoMapEnd,		  NULL,		 0,				0,			   NULL,		  NULL, 0x00}
sl@0
   227
	};
sl@0
   228
sl@0
   229
const SRegisterMapInfo* FindIoEntryFromID(const SRegisterMapInfo* aIoMapP, TUint32 aID)
sl@0
   230
	{
sl@0
   231
	const SRegisterMapInfo* foundEntry = NULL;
sl@0
   232
	
sl@0
   233
	TInt currentEntry = 0;
sl@0
   234
	
sl@0
   235
	while((aIoMapP[currentEntry].iRegisterID != KIoMapEnd) && (foundEntry == NULL))
sl@0
   236
		{
sl@0
   237
		if(aIoMapP[currentEntry].iRegisterID == aID)
sl@0
   238
			{
sl@0
   239
			foundEntry = aIoMapP+currentEntry;
sl@0
   240
			}
sl@0
   241
		currentEntry++;
sl@0
   242
		}
sl@0
   243
sl@0
   244
	return(foundEntry);
sl@0
   245
	}
sl@0
   246
sl@0
   247
const SRegisterMapInfo* FindIoEntryFromAddress(const SRegisterMapInfo* aIoMapP, TUint32 aAddr)
sl@0
   248
	{
sl@0
   249
	const SRegisterMapInfo* foundEntry = NULL;
sl@0
   250
	
sl@0
   251
	TInt currentEntry = 0;
sl@0
   252
	
sl@0
   253
	while((aIoMapP[currentEntry].iRegisterID != KIoMapEnd) && (foundEntry == NULL))
sl@0
   254
		{
sl@0
   255
		const TUint32 startAddr = aIoMapP[currentEntry].iAddress;
sl@0
   256
		const TUint32 endAddr   = startAddr + aIoMapP[currentEntry].iLength - 1;
sl@0
   257
		
sl@0
   258
		if((aAddr >= startAddr) && (aAddr <= endAddr))
sl@0
   259
			{
sl@0
   260
			if(aIoMapP[currentEntry].iChildMapP)
sl@0
   261
				{
sl@0
   262
				foundEntry = FindIoEntryFromAddress(aIoMapP[currentEntry].iChildMapP, aAddr);
sl@0
   263
				}
sl@0
   264
			else
sl@0
   265
				{
sl@0
   266
				foundEntry = aIoMapP+currentEntry;
sl@0
   267
				}
sl@0
   268
			}
sl@0
   269
		currentEntry++;
sl@0
   270
		}
sl@0
   271
sl@0
   272
	return(foundEntry);
sl@0
   273
	}
sl@0
   274
sl@0
   275
sl@0
   276
sl@0
   277
// ======== error code conversion ========
sl@0
   278
sl@0
   279
GLDEF_C TInt MapLastErrorEpoc()
sl@0
   280
//
sl@0
   281
// map an Win32 error code to Epoc32 value
sl@0
   282
//
sl@0
   283
	{
sl@0
   284
	TInt res=KErrGeneral;
sl@0
   285
	switch (GetLastError())
sl@0
   286
		{
sl@0
   287
		case ERROR_SHARING_VIOLATION : res=KErrAccessDenied; break;
sl@0
   288
		case ERROR_LOCK_VIOLATION : res=KErrLocked; break;
sl@0
   289
		case ERROR_FILE_NOT_FOUND: res=KErrNotFound; break;
sl@0
   290
		case ERROR_PATH_NOT_FOUND: res=KErrPathNotFound; break;
sl@0
   291
		case ERROR_ALREADY_EXISTS:
sl@0
   292
		case ERROR_FILE_EXISTS:
sl@0
   293
			res=KErrAlreadyExists;
sl@0
   294
			break;
sl@0
   295
		case ERROR_NOT_READY: res=KErrNotReady; break;
sl@0
   296
		case ERROR_UNRECOGNIZED_VOLUME:
sl@0
   297
		case ERROR_NOT_DOS_DISK:
sl@0
   298
			res=KErrUnknown;
sl@0
   299
			break;
sl@0
   300
		case ERROR_UNRECOGNIZED_MEDIA: res=KErrCorrupt; break;
sl@0
   301
		case ERROR_INVALID_NAME: res=KErrBadName; break;
sl@0
   302
		case ERROR_NO_MORE_FILES: res=KErrEof; break;
sl@0
   303
		}
sl@0
   304
	return(res);
sl@0
   305
	}
sl@0
   306
sl@0
   307
GLDEF_C TMMCErr MapLastErrorMmc()
sl@0
   308
//
sl@0
   309
// map Win32 error to a TMMCErr error.
sl@0
   310
//
sl@0
   311
	{
sl@0
   312
	DWORD r=GetLastError();
sl@0
   313
	TInt res=KErrGeneral;
sl@0
   314
	switch (r)
sl@0
   315
		{
sl@0
   316
		case ERROR_SHARING_VIOLATION:
sl@0
   317
		case ERROR_LOCK_VIOLATION:
sl@0
   318
			res=KMMCErrLocked;			// KErrLocked
sl@0
   319
			break;
sl@0
   320
		case ERROR_FILE_NOT_FOUND:
sl@0
   321
		case ERROR_PATH_NOT_FOUND:
sl@0
   322
			res=KMMCErrNotFound;		// KErrNotFound
sl@0
   323
			break;
sl@0
   324
		case ERROR_ALREADY_EXISTS:
sl@0
   325
		case ERROR_FILE_EXISTS:
sl@0
   326
			res=KMMCErrAlreadyExists;	// KErrAlreadyExists
sl@0
   327
			break;
sl@0
   328
		case ERROR_NOT_READY: res=KMMCErrNoCard; break;
sl@0
   329
		case ERROR_UNRECOGNIZED_VOLUME:
sl@0
   330
		case ERROR_NOT_DOS_DISK:
sl@0
   331
			res=KMMCErrGeneral;			// KErrGeneral
sl@0
   332
			break;
sl@0
   333
		case ERROR_UNRECOGNIZED_MEDIA:
sl@0
   334
		case ERROR_INVALID_NAME:
sl@0
   335
		case ERROR_NO_MORE_FILES:
sl@0
   336
			res=KMMCErrResponseCRC; 	// KErrCorrupt
sl@0
   337
			break;
sl@0
   338
		}
sl@0
   339
	return(res);
sl@0
   340
	}
sl@0
   341
sl@0
   342
// ======== DWinsSDIOStack ========
sl@0
   343
sl@0
   344
DWinsSDIOStack::DWinsSDIOStack(TInt aBus, DMMCSocket* aSocket)
sl@0
   345
  : DSDIOStack(aBus, aSocket),
sl@0
   346
	iEnableTimer(&DWinsSDIOStack::EnableTimerCallback,this)
sl@0
   347
	{	
sl@0
   348
	iAddressedCard=KBroadcastToAllCards;
sl@0
   349
//	iCMD42Failed=EFalse;
sl@0
   350
	}
sl@0
   351
sl@0
   352
sl@0
   353
TInt DWinsSDIOStack::Init()
sl@0
   354
//
sl@0
   355
// Allocate any resources. Only created once on kernel initialization so dont
sl@0
   356
// worry about cleanup if it leaves.
sl@0
   357
//
sl@0
   358
	{
sl@0
   359
	if((iCardArray = new TSDIOCardArray(this)) == NULL)
sl@0
   360
		return KErrNoMemory;
sl@0
   361
sl@0
   362
	TInt r=DMMCStack::Init();
sl@0
   363
	if(r!=KErrNone)
sl@0
   364
		return r;
sl@0
   365
sl@0
   366
	DMediaChangeBase* pMCBase = MMCSocket()->iMediaChange;
sl@0
   367
	static_cast<DWinsMMCMediaChange*>(pMCBase)->SetStackP(this);
sl@0
   368
	Wins::SetMediaChangeCallBackPtr(DWinsMMCMediaChange::MediaChangeCallBack, (TAny*)pMCBase);
sl@0
   369
sl@0
   370
	//
sl@0
   371
	// Over time memory can become fragmented, and so it is not possible to
sl@0
   372
	// allocate physically contiguous pages.  Therefore, the buffers for IO
sl@0
   373
	// are allocated at startup.
sl@0
   374
	//
sl@0
   375
	// block and erase sector size characteristics depend on the specific
sl@0
   376
	// card model, and so the initial values are estimates based on a typical
sl@0
   377
	// card.  If these do not match the actual card's block size (or erase
sl@0
   378
	// size, for SD,) then the media driver just gets a reduced or increased
sl@0
   379
	// buffer area, and its efficiency varies accordingly.
sl@0
   380
	//
sl@0
   381
	// For the WINS implementation, fragmentation does not matter because
sl@0
   382
	// DMA is not used.  The memory must still be allocated here so MEDMMC is
sl@0
   383
	// able to use it.
sl@0
   384
	//
sl@0
   385
	// The constant calculations could be folded, but this illustrates how the
sl@0
   386
	// values are derived.
sl@0
   387
	//
sl@0
   388
sl@0
   389
	// MMC - values from Hitachi 16Mb card, datasheet HB288016MM1
sl@0
   390
sl@0
   391
	// minor buffer must contain enough space for MBR or block
sl@0
   392
	const TUint mmcBlkSzLog2 = 9;				// READ_BLK_LEN and WRITE_BLK_LEN
sl@0
   393
	const TUint mmcBlkSz = 1 << mmcBlkSzLog2;
sl@0
   394
	const TInt mmcMinorBufLen = Max(KDiskSectorSize, mmcBlkSz);
sl@0
   395
sl@0
   396
	const TInt KMinMMCBlocksInBuffer = 8;
sl@0
   397
	const TInt mmcCchBufLen = KMinMMCBlocksInBuffer << mmcBlkSzLog2;
sl@0
   398
sl@0
   399
	const TInt mmcTotalBufLen = mmcMinorBufLen + mmcCchBufLen;
sl@0
   400
sl@0
   401
	// SDCard - values from 64Mb Panasonic RP-SD064
sl@0
   402
sl@0
   403
	const TUint sdBlkSzLog2 = 9;				// READ_BL_LEN and WRITE_BLK_LEN
sl@0
   404
	const TUint sdBlkSz = 1 << sdBlkSzLog2;
sl@0
   405
	const TInt sdMinorBufLen = Max(KDiskSectorSize, sdBlkSz);
sl@0
   406
sl@0
   407
	const TUint ss = 0x1f;						// SECTOR_SIZE, add 1 for sector count
sl@0
   408
	const TInt KMinSDBlocksInBuffer = 8;
sl@0
   409
	const TInt sdCchBufLen = Max(KMinSDBlocksInBuffer, ss + 1) << sdBlkSzLog2;
sl@0
   410
sl@0
   411
	const TInt sdTotalBufLen = sdMinorBufLen + sdCchBufLen;
sl@0
   412
sl@0
   413
	const TInt totalBufLen = Max(mmcTotalBufLen, sdTotalBufLen);
sl@0
   414
sl@0
   415
	iMDBuf = reinterpret_cast<TUint8*>(Kern::Alloc(totalBufLen));
sl@0
   416
	iMDBufLen = totalBufLen;
sl@0
   417
sl@0
   418
	// initialize each card on the stack
sl@0
   419
	TInt i;
sl@0
   420
	for (i = 0; i < KTotalWinsCards; ++i)
sl@0
   421
		{
sl@0
   422
		TInt r = SetupSimulatedCard(i);
sl@0
   423
		if (r != KErrNone)
sl@0
   424
			return r;
sl@0
   425
		}
sl@0
   426
sl@0
   427
	// initialize pointers to currently present cards
sl@0
   428
sl@0
   429
	// Slot zero can toggle between no card; card 0 and card 1.  The current state is
sl@0
   430
	// determined by *Wins::CurrentPBusDevicePtr() and toggled by pressing F4 when F5
sl@0
   431
	// (door open) is held down.  Because this function is only executed at startup,
sl@0
   432
	// assume start with card zero.
sl@0
   433
	iCardInfo[0] = iCardPool[0];
sl@0
   434
	for (i = 1; i < KTotalWinsCardSlots; ++i)
sl@0
   435
		{
sl@0
   436
		iCardInfo[i]=iCardPool[i+1];
sl@0
   437
		}
sl@0
   438
sl@0
   439
	return KErrNone;
sl@0
   440
	}
sl@0
   441
sl@0
   442
void DWinsSDIOStack::MachineInfo(TMMCMachineInfo& aMachineInfo)
sl@0
   443
	{
sl@0
   444
	aMachineInfo.iTotalSockets=KTotalWinsCardSlots;
sl@0
   445
	aMachineInfo.iTotalMediaChanges=0;  		// Not used at present
sl@0
   446
	aMachineInfo.iTotalPrimarySupplies=0;		// Not used at present
sl@0
   447
sl@0
   448
	aMachineInfo.iSPIMode=EFalse;
sl@0
   449
    aMachineInfo.iBaseBusNumber=0;
sl@0
   450
sl@0
   451
	__ASSERT_DEBUG(aMachineInfo.iTotalSockets<=KMaxMMCardsPerStack,
sl@0
   452
					DWinsSDIOStack::Panic(DWinsSDIOStack::EWinsMMCBadMachineInfo));
sl@0
   453
	}
sl@0
   454
sl@0
   455
void DWinsSDIOStack::AdjustPartialRead(
sl@0
   456
#ifdef _DEBUG
sl@0
   457
	const TMMCard* aCard,
sl@0
   458
#else
sl@0
   459
	const TMMCard* /*aCard*/,
sl@0
   460
#endif
sl@0
   461
	TUint32 aStart, TUint32 aEnd, TUint32* aPhysStart, TUint32* aPhysEnd) const
sl@0
   462
	{
sl@0
   463
#ifdef _DEBUG
sl@0
   464
	const TUint32 blkLen = aCard->CSD().ReadBlockLength();
sl@0
   465
	const TUint32 blkMsk = blkLen - 1;
sl@0
   466
sl@0
   467
	__ASSERT_DEBUG(aCard->CSD().ReadBlPartial(), Panic(EWinsMMCAPRNotSupp));
sl@0
   468
	__ASSERT_DEBUG(aEnd - aStart <= blkLen, Panic(EWinsMMCAPRRange));
sl@0
   469
	__ASSERT_DEBUG((aEnd & ~blkMsk) > (aStart & ~blkMsk), Panic(EWinsMMCAPRBoundary));
sl@0
   470
#endif
sl@0
   471
sl@0
   472
	*aPhysStart = aStart & ~0x3;
sl@0
   473
	*aPhysEnd = (aEnd + 0x3) & ~0x3;
sl@0
   474
	}
sl@0
   475
sl@0
   476
void DWinsSDIOStack::GetBufferInfo(TUint8** aMDBuf, TInt* aMDBufLen)
sl@0
   477
	{
sl@0
   478
	*aMDBuf = iMDBuf;
sl@0
   479
	*aMDBufLen = iMDBufLen;
sl@0
   480
	}
sl@0
   481
sl@0
   482
void DWinsSDIOStack::Panic(TWinsMMCPanic aPanic)
sl@0
   483
	{
sl@0
   484
	_LIT(KPncNm,"PBUS-MMCSD-WINS");
sl@0
   485
	Kern::PanicCurrentThread(KPncNm,aPanic);
sl@0
   486
	}
sl@0
   487
sl@0
   488
TInt DWinsSDIOStack::SetupSimulatedCard(TInt aCardNum)
sl@0
   489
//
sl@0
   490
// allocate individual card with Win32 file.  Only called at bootup, so no cleanup if fails.
sl@0
   491
//
sl@0
   492
	{
sl@0
   493
	TWinsCardInfo* cip = new TWinsCardInfo;
sl@0
   494
	if (cip == 0)
sl@0
   495
		return KErrNoMemory;
sl@0
   496
sl@0
   497
	TUint8 cid[KMMCCIDLength];
sl@0
   498
	cid[0] = 'C';
sl@0
   499
	cid[1] = 'I';
sl@0
   500
	cid[2] = 'D';
sl@0
   501
	cid[3] = TUint8('0' + aCardNum);
sl@0
   502
	TInt j;
sl@0
   503
	for (j = 4; j < KMMCCIDLength - 1; ++j)
sl@0
   504
		cid[j] = 'c';
sl@0
   505
	cid[KMMCCIDLength - 1] = '#';				// '#' = 0x23, bit zero must be 1
sl@0
   506
	cip->iCID=cid;
sl@0
   507
sl@0
   508
	cip->iPWD = new TMediaPassword;
sl@0
   509
	if (! cip->iPWD)
sl@0
   510
		{
sl@0
   511
		delete cip;
sl@0
   512
		return KErrNoMemory;
sl@0
   513
		}
sl@0
   514
sl@0
   515
	// cards in slot zero are SD
sl@0
   516
	TInt mediaAreas;
sl@0
   517
	if (aCardNum <= 1)
sl@0
   518
		{
sl@0
   519
		cip->iIsSDCard = ETrue;
sl@0
   520
		mediaAreas = 3;	// +1 for SDIO area
sl@0
   521
		}
sl@0
   522
	else
sl@0
   523
		{
sl@0
   524
		cip->iIsSDCard = EFalse;
sl@0
   525
		mediaAreas = 1;
sl@0
   526
		}
sl@0
   527
sl@0
   528
	cip->iState=ECardStateIdle;
sl@0
   529
sl@0
   530
	for (TInt area = 0; area < mediaAreas; ++area)
sl@0
   531
		{
sl@0
   532
		TInt r = CreateBinFileForCard(aCardNum, area, &cip->iAreaHandles[area]);
sl@0
   533
		if (r != KErrNone)
sl@0
   534
			return r;
sl@0
   535
		}
sl@0
   536
	iCardPool[aCardNum]=cip;
sl@0
   537
	return(KErrNone);
sl@0
   538
	}
sl@0
   539
sl@0
   540
TInt DWinsSDIOStack::CreateBinFileForCard(TInt aCardNum, TInt aAreaNum, HANDLE* aHandle)
sl@0
   541
//
sl@0
   542
// create .bin file in temp directory to contain media area of card.
sl@0
   543
//
sl@0
   544
	{
sl@0
   545
	const char* emulatorPath = Property::GetString("EmulatorMediaPath");
sl@0
   546
	if (!Emulator::CreateAllDirectories(emulatorPath))
sl@0
   547
		return Emulator::LastError();
sl@0
   548
sl@0
   549
	TBuf8<KMaxFileName> fn8(_L8(emulatorPath));
sl@0
   550
	fn8.Append(_L8("MMCCRD"));
sl@0
   551
	fn8.AppendNum(aCardNum);
sl@0
   552
	fn8.Append('A'+aAreaNum);
sl@0
   553
	fn8.Append(_L8(".BIN"));
sl@0
   554
	fn8.Append('\0');
sl@0
   555
sl@0
   556
	*aHandle = CreateFileA(
sl@0
   557
		(LPCSTR) fn8.Ptr(),					// LPCSTR lpFileName,
sl@0
   558
		GENERIC_READ | GENERIC_WRITE,		// DWORD dwDesiredAccess
sl@0
   559
		FILE_SHARE_READ | FILE_SHARE_WRITE,	// DWORD dwShareMode
sl@0
   560
		NULL,								// LPSECURITY_ATTRIBUTES lpSecurityAttributes
sl@0
   561
		OPEN_ALWAYS,						// DWORD dwCreationDisposition
sl@0
   562
		FILE_FLAG_RANDOM_ACCESS,			// DWORD dwFlagsAndAttributes
sl@0
   563
		NULL);								// HANDLE hTemplateFile
sl@0
   564
sl@0
   565
	if (*aHandle == INVALID_HANDLE_VALUE)
sl@0
   566
	    return MapLastErrorEpoc();
sl@0
   567
	
sl@0
   568
	if (	SetFilePointer(*aHandle, KTotalMDiskSize, NULL, FILE_BEGIN) == 0xffffffffu
sl@0
   569
		||	! SetEndOfFile(*aHandle) )
sl@0
   570
		{
sl@0
   571
		CloseHandle(*aHandle);
sl@0
   572
	    return MapLastErrorEpoc();
sl@0
   573
		}
sl@0
   574
sl@0
   575
	return KErrNone;
sl@0
   576
	}
sl@0
   577
sl@0
   578
void DWinsSDIOStack::SetBusConfigDefaults(TMMCBusConfig& aConfig, TUint aClock)
sl@0
   579
	{
sl@0
   580
	const TUint KWinsMaxHwInterfaceClk=104000;
sl@0
   581
	const TUint KWinsResponseTimeOut=6400;
sl@0
   582
	const TUint KWinsDataTimeOut=40000;
sl@0
   583
	const TUint KWinsBusyTimeOut=200000;
sl@0
   584
sl@0
   585
	aConfig.iBusClock = (aClock > KWinsMaxHwInterfaceClk) ? KWinsMaxHwInterfaceClk : aClock;
sl@0
   586
	aConfig.iResponseTimeOut=KWinsResponseTimeOut;
sl@0
   587
	aConfig.iDataTimeOut=KWinsDataTimeOut;
sl@0
   588
	aConfig.iBusyTimeOut=KWinsBusyTimeOut;
sl@0
   589
	}
sl@0
   590
sl@0
   591
void DWinsSDIOStack::InitClockOff()
sl@0
   592
	{
sl@0
   593
	// empty.
sl@0
   594
	}
sl@0
   595
sl@0
   596
void DWinsSDIOStack::ASSPReset()
sl@0
   597
	{
sl@0
   598
	// empty.
sl@0
   599
	}
sl@0
   600
sl@0
   601
void DWinsSDIOStack::ASSPDisengage()
sl@0
   602
	{
sl@0
   603
	// empty.
sl@0
   604
	}
sl@0
   605
sl@0
   606
void DWinsSDIOStack::DoPowerDown()
sl@0
   607
	{
sl@0
   608
	// empty.
sl@0
   609
	}
sl@0
   610
sl@0
   611
sl@0
   612
LOCAL_C TInt SetMediaPasswordEnvironmentVar(TInt aSocketNum,TInt aCardNum,const TDesC8& aPasswd)
sl@0
   613
// 
sl@0
   614
// Set the password for local drive 'aLocalDrive', card number 'aCardNum' to 'aPasswd' - as an
sl@0
   615
// environment variable. Note that the card number is only relevant where the emulated drive
sl@0
   616
// supports card hot-swapping (i.e. F4 whilst F5 is held down).
sl@0
   617
//
sl@0
   618
	{
sl@0
   619
	// Setup the appropriate environment variable string '_EPOC_LocDrv_<locDrvNum>_PWORD_<cardNum>'
sl@0
   620
	TUint16 envVar[]=L"_EPOC_Socket_X_PWORD_Y";
sl@0
   621
sl@0
   622
	envVar[13]=(TUint16)('0'+aSocketNum);
sl@0
   623
	envVar[21]=(TUint16)('0'+aCardNum);
sl@0
   624
	
sl@0
   625
	// Setup the new value of the environment variable
sl@0
   626
	TUint16	envVal[100];
sl@0
   627
	TInt len=aPasswd.Length();
sl@0
   628
sl@0
   629
	// the password may be empty if a card's password is cleared
sl@0
   630
	if (len>(100-1))
sl@0
   631
		return(KErrArgument);
sl@0
   632
	memcpy(&envVal[0],reinterpret_cast<const TUint16 *>(aPasswd.Ptr()),len);
sl@0
   633
	envVal[len>>1]='\0';
sl@0
   634
sl@0
   635
	// Now set the new value for the environment variable
sl@0
   636
	if (SetEnvironmentVariable(envVar,&envVal[0]))
sl@0
   637
		return(KErrNone);
sl@0
   638
sl@0
   639
	return KErrGeneral;
sl@0
   640
	}
sl@0
   641
sl@0
   642
LOCAL_C TInt MediaPasswordEnvironmentVar(TInt aSocketNum,TInt aCardNum,TDes8& aPasswd)
sl@0
   643
// 
sl@0
   644
// Get the password for local drive 'aLocalDrive', card number 'aCardNum' into 'aPasswd' - from
sl@0
   645
// an environment variable. Note that the card number is only relevant where the emulated drive
sl@0
   646
// supports card hot-swapping (i.e. F4 whilst F5 is held down).
sl@0
   647
//
sl@0
   648
	{
sl@0
   649
	TUint16 envVar[]=L"_EPOC_Socket_X_PWORD_Y";
sl@0
   650
sl@0
   651
	envVar[13]=(TUint16)('0'+aSocketNum);
sl@0
   652
	envVar[21]=(TUint16)('0'+aCardNum);
sl@0
   653
	
sl@0
   654
	TUint16 envVal[100];	// To hold the value of the retreived environment variable
sl@0
   655
	
sl@0
   656
	DWORD len=GetEnvironmentVariable(envVar,&envVal[0],100);
sl@0
   657
	if (len>(TUint)100)
sl@0
   658
		return(KErrGeneral);
sl@0
   659
	if (len)
sl@0
   660
		{
sl@0
   661
		// Found the requested environment variable so there is a password for this local drive / card. 
sl@0
   662
		if ((len<<1)<=KMaxMediaPassword)
sl@0
   663
			{
sl@0
   664
			aPasswd.FillZ(KMaxMediaPassword);
sl@0
   665
			aPasswd.Zero();
sl@0
   666
			aPasswd.Copy(reinterpret_cast<TUint8*>(&envVal[0]),len<<1);
sl@0
   667
			return(KErrNone);	
sl@0
   668
			}
sl@0
   669
		else	
sl@0
   670
			return(KErrGeneral);	
sl@0
   671
		}
sl@0
   672
sl@0
   673
	return(KErrNotFound);
sl@0
   674
	}
sl@0
   675
sl@0
   676
TMMCErr DWinsSDIOStack::DoPowerUpSM()
sl@0
   677
	{
sl@0
   678
	enum states
sl@0
   679
		{
sl@0
   680
		EStBegin=0,
sl@0
   681
		EStEnd
sl@0
   682
		};
sl@0
   683
sl@0
   684
	SMF_BEGIN
sl@0
   685
sl@0
   686
		if(MMCSocket()->iVcc->SetState(EPsuOnCurLimit) != KErrNone)
sl@0
   687
			return KMMCErrHardware;
sl@0
   688
sl@0
   689
		for (TInt i = 0; i < KTotalWinsCardSlots; ++i)
sl@0
   690
			{
sl@0
   691
			// if card has a password, it will be locked on power up
sl@0
   692
			TInt cardNum = (i==0) ? *Wins::CurrentPBusDevicePtr() : i + 1;
sl@0
   693
			if (	cardNum >= 0
sl@0
   694
				&&	MediaPasswordEnvironmentVar(
sl@0
   695
						MMCSocket()->iSocketNumber, cardNum, *(iCardInfo[i]->iPWD))
sl@0
   696
					==	KErrNone)
sl@0
   697
				{
sl@0
   698
				iCardInfo[i]->iIsLocked = (iCardInfo[i]->iPWD->Length() > 0);
sl@0
   699
				}
sl@0
   700
			else	
sl@0
   701
				iCardInfo[i]->iIsLocked=EFalse;
sl@0
   702
sl@0
   703
			iCardInfo[i]->iState = ECardStateIdle;
sl@0
   704
			iCardInfo[i]->iRCA=0x0001;		// Default RCA - spec 2.2, s4.2.1, 5.4
sl@0
   705
			}
sl@0
   706
sl@0
   707
		ReportPowerUp();
sl@0
   708
sl@0
   709
	SMF_END
sl@0
   710
	}
sl@0
   711
sl@0
   712
TMMCErr DWinsSDIOStack::InitClockOnSM()
sl@0
   713
	{
sl@0
   714
	enum states
sl@0
   715
		{
sl@0
   716
		EStBegin=0,
sl@0
   717
		EStEnd
sl@0
   718
		};
sl@0
   719
	SMF_BEGIN
sl@0
   720
sl@0
   721
	SMF_END
sl@0
   722
	}
sl@0
   723
sl@0
   724
void DWinsSDIOStack::AddressCard(TInt aCardNumber)
sl@0
   725
	{
sl@0
   726
	iAddressedCard = aCardNumber;
sl@0
   727
	}
sl@0
   728
sl@0
   729
sl@0
   730
TInt DWinsSDIOStack::GetTargetSlotNumber(const TRCA& anRCA)
sl@0
   731
//
sl@0
   732
// when the controller is given a command with an embedded RCA, this function
sl@0
   733
// works out which physical card slot it corresponds to.  If no card has been
sl@0
   734
// assigned the RCA then it returns -1.
sl@0
   735
//
sl@0
   736
	{
sl@0
   737
	TInt targetIdx = -1;
sl@0
   738
sl@0
   739
	for (TInt i = 0; i < KTotalWinsCardSlots; ++i)
sl@0
   740
		{
sl@0
   741
		if (iCardInfo[i]->iRCA==anRCA)
sl@0
   742
			{
sl@0
   743
			targetIdx=i;
sl@0
   744
			break;
sl@0
   745
			}
sl@0
   746
		}
sl@0
   747
sl@0
   748
	return(targetIdx);
sl@0
   749
	}
sl@0
   750
sl@0
   751
TMMCErr DWinsSDIOStack::IssueMMCCommandSM()
sl@0
   752
	{
sl@0
   753
	enum states
sl@0
   754
		{
sl@0
   755
		EStBegin=0,
sl@0
   756
		EStEnd
sl@0
   757
		};
sl@0
   758
sl@0
   759
	TMMCCommandDesc& cmd = Command();
sl@0
   760
sl@0
   761
	// If the command contains an embedded RCA then extract it	
sl@0
   762
	TRCA tgtRCA=0;
sl@0
   763
	TBool supRCA=EFalse;
sl@0
   764
	if (/*cmd.iCommand == ECmdSetRelativeAddr	||	*/cmd.iCommand == ECmdSelectCard
sl@0
   765
	||	cmd.iCommand == ECmdSendCSD			||	cmd.iCommand == ECmdSendCID
sl@0
   766
	||	cmd.iCommand == ECmdSendStatus		||	cmd.iCommand == ECmdGoInactiveState
sl@0
   767
	||	cmd.iCommand == ECmdFastIO 			||  cmd.iCommand == ECmdAppCmd )
sl@0
   768
		{
sl@0
   769
		if ((cmd.iArgument >> 16) != 0)
sl@0
   770
			{
sl@0
   771
			supRCA=ETrue;
sl@0
   772
			tgtRCA=TUint16(cmd.iArgument >> 16);
sl@0
   773
			}
sl@0
   774
		}
sl@0
   775
sl@0
   776
	// if the card contains an embedded RCA, work out which slot it corresponds to.
sl@0
   777
	// At the end of the function, this card is used to generate the R1 response.
sl@0
   778
	// Assume that if rca is supplied it either corresponds to the selected card or
sl@0
   779
	// broadcast mode is on.  (An exception is CMD7 with arg0 to deselect all cards.)
sl@0
   780
sl@0
   781
	TInt targetCard = supRCA ? GetTargetSlotNumber(tgtRCA) : iAddressedCard;
sl@0
   782
	TBool rto = EFalse;							// response timeout
sl@0
   783
sl@0
   784
	// if try to access card zero has been set to holding no card via F5 / F4 then timeout.
sl@0
   785
	if ((targetCard == 0) && *Wins::CurrentPBusDevicePtr() < 0)
sl@0
   786
		return KMMCErrResponseTimeOut;
sl@0
   787
	
sl@0
   788
	HANDLE winHandle;
sl@0
   789
sl@0
   790
	// CMD42 is a data transfer command.  That means the R1 response that it returns
sl@0
   791
	// immediately is the state it is in on receiving the data block, and not after
sl@0
   792
	// processing it.  If the data block is invalid then LOCK_UNLOCK_FAILED will be
sl@0
   793
	// set in the R1 response which is sent in reply to the next command.
sl@0
   794
sl@0
   795
	TBool nextCMD42Failed = EFalse;
sl@0
   796
	TBool lock_unlock_failed=EFalse;
sl@0
   797
sl@0
   798
	// When the card is locked, it will only respond to basic command class (0) and
sl@0
   799
	// lock card command class (7).  An exception is CMD16.  This is sent before CMD42,
sl@0
   800
	// but is classified (MMC Spec 23.2, table 5) as belonging to classes 2 and 4.
sl@0
   801
	// For data transfer commands, LOCK_UNLOCK_FAIL is set in response to the following
sl@0
   802
sl@0
   803
	TMMCCommandEnum origCmd = cmd.iCommand;
sl@0
   804
sl@0
   805
	// if targetting locked card...
sl@0
   806
	if (targetCard != KBroadcastToAllCards && iCardInfo[targetCard]->iIsLocked)
sl@0
   807
		{
sl@0
   808
		// ...and not command used in init or CMD42 sequence...
sl@0
   809
		if (!(	((cmd.iSpec.iCommandClass & (KMMCCmdClassApplication | KMMCCmdClassBasic | KMMCCmdClassLockCard)) != 0)
sl@0
   810
			||	(cmd.iCommand == ECmdSetBlockLen) || (cmd.iCommand == ECmdAppCmd) ))
sl@0
   811
			{
sl@0
   812
			lock_unlock_failed = ETrue;
sl@0
   813
			cmd.iCommand = (TMMCCommandEnum) -1;	// skip case processing
sl@0
   814
			}
sl@0
   815
		}
sl@0
   816
sl@0
   817
	SMF_BEGIN
sl@0
   818
sl@0
   819
	switch (cmd.iCommand)
sl@0
   820
		{
sl@0
   821
		case ECmdGoIdleState:	// CMD0
sl@0
   822
			if (iAddressedCard != KBroadcastToAllCards)
sl@0
   823
				iCardInfo[iAddressedCard]->iState = ECardStateIdle;
sl@0
   824
			else
sl@0
   825
				{
sl@0
   826
				for (TInt i = 0; i < KTotalWinsCardSlots; ++i)
sl@0
   827
					iCardInfo[i]->iState = ECardStateIdle;
sl@0
   828
				}
sl@0
   829
			break;
sl@0
   830
sl@0
   831
		case ECmd41:
sl@0
   832
		case ECmdSendOpCond:	// CMD1
sl@0
   833
			{
sl@0
   834
			if (iAddressedCard != KBroadcastToAllCards)
sl@0
   835
				iCardInfo[iAddressedCard]->iState = ECardStateReady;
sl@0
   836
			else
sl@0
   837
				{
sl@0
   838
				for (TInt i = 0; i < KTotalWinsCardSlots; ++i)
sl@0
   839
					iCardInfo[i]->iState = ECardStateReady;
sl@0
   840
				}
sl@0
   841
sl@0
   842
			// bit31 is set to indicate cards are not still powering up
sl@0
   843
			TUint32 r3 = KMMCWinsCardOCRValue | KMMCOCRBusy;
sl@0
   844
			TMMC::BigEndian4Bytes(cmd.iResponse, r3);
sl@0
   845
			}
sl@0
   846
			break;
sl@0
   847
sl@0
   848
		case ECmdAllSendCID:	// CMD2
sl@0
   849
			{
sl@0
   850
			TInt idx;
sl@0
   851
			if (iAddressedCard != KBroadcastToAllCards)
sl@0
   852
				{
sl@0
   853
				idx = iAddressedCard;
sl@0
   854
				__ASSERT_DEBUG(
sl@0
   855
					iCardInfo[iAddressedCard]->iState == ECardStateReady,
sl@0
   856
					DWinsSDIOStack::Panic(DWinsSDIOStack::EStkIMCBadStateCmd2));
sl@0
   857
				}
sl@0
   858
			else
sl@0
   859
				idx = FindAnyCardInStack(ECardStateReady);
sl@0
   860
sl@0
   861
			if (idx == -1)
sl@0
   862
				rto = ETrue;
sl@0
   863
			else
sl@0
   864
				{
sl@0
   865
				iCardInfo[idx]->iCID.Copy(cmd.iResponse);
sl@0
   866
				iCardInfo[idx]->iState = ECardStateIdent;
sl@0
   867
				}
sl@0
   868
			}
sl@0
   869
			break;
sl@0
   870
sl@0
   871
		case ECmdSetRelativeAddr:	// CMD3
sl@0
   872
			{
sl@0
   873
			TInt idx;
sl@0
   874
			if (iAddressedCard != KBroadcastToAllCards)
sl@0
   875
				{
sl@0
   876
				__ASSERT_DEBUG(
sl@0
   877
					iCardInfo[iAddressedCard]->iState == ECardStateIdent,
sl@0
   878
					DWinsSDIOStack::Panic(DWinsSDIOStack::EStkIMCBadStateCmd3));
sl@0
   879
				
sl@0
   880
				if (iCardInfo[iAddressedCard]->iIsSDCard)
sl@0
   881
					{
sl@0
   882
					static TUint16 RCACounter = 0x1234;
sl@0
   883
					// SD Cards publish RCAs
sl@0
   884
					++RCACounter;
sl@0
   885
					iCardInfo[iAddressedCard]->iRCA = RCACounter;
sl@0
   886
					iCardInfo[iAddressedCard]->iState = ECardStateStby;
sl@0
   887
					TUint32 r6 = TUint32(RCACounter) << 16;
sl@0
   888
					TMMC::BigEndian4Bytes(&cmd.iResponse[0],r6); // Ignore bits 47-40
sl@0
   889
					}
sl@0
   890
				else
sl@0
   891
					{
sl@0
   892
					iCardInfo[iAddressedCard]->iRCA = TUint16(cmd.iArgument >> 16);
sl@0
   893
					iCardInfo[iAddressedCard]->iState=ECardStateStby;
sl@0
   894
					}
sl@0
   895
				}
sl@0
   896
			else
sl@0
   897
				{
sl@0
   898
				// MultiMediaCards are assigned RCAs
sl@0
   899
				idx = FindOneCardInStack(ECardStateIdent);
sl@0
   900
				iCardInfo[iAddressedCard]->iRCA = TUint16(cmd.iArgument >> 16);
sl@0
   901
				iCardInfo[iAddressedCard]->iState=ECardStateStby;
sl@0
   902
				targetCard = iAddressedCard;
sl@0
   903
				}
sl@0
   904
			}
sl@0
   905
			break;
sl@0
   906
sl@0
   907
		case ECmd6:
sl@0
   908
			// if ACMD6 then change bus width
sl@0
   909
			if (cmd.iSpec.iCommandClass == KMMCCmdClassApplication)
sl@0
   910
				{
sl@0
   911
				switch (cmd.iArgument)
sl@0
   912
					{
sl@0
   913
				case 0x00:
sl@0
   914
					iCardInfo[iAddressedCard]->iBusWidth = 1;
sl@0
   915
					break;
sl@0
   916
				case 0x02:
sl@0
   917
					iCardInfo[iAddressedCard]->iBusWidth = 4;
sl@0
   918
					break;
sl@0
   919
				default:
sl@0
   920
					DWinsSDIOStack::Panic(DWinsSDIOStack::EStkIMCCmd6InvalidWidth);
sl@0
   921
					break;
sl@0
   922
					}
sl@0
   923
				}
sl@0
   924
			break;
sl@0
   925
sl@0
   926
		case ECmdSelectCard:		// CMD7
sl@0
   927
			{
sl@0
   928
			// switch to broadcast mode so the currently selected and new cards
sl@0
   929
			// receive the command simultaneously.
sl@0
   930
sl@0
   931
			TInt idx = FindAnyCardInStack(ECardStateTran);
sl@0
   932
			if (idx != -1)
sl@0
   933
				iCardInfo[idx]->iState = ECardStateStby;
sl@0
   934
			if ((iAddressedCard=targetCard) == KBroadcastToAllCards)
sl@0
   935
				rto = ETrue;
sl@0
   936
			else
sl@0
   937
				{
sl@0
   938
				iCardInfo[targetCard]->iState = ECardStateTran;
sl@0
   939
				targetCard = targetCard;
sl@0
   940
				}
sl@0
   941
			}
sl@0
   942
			break;
sl@0
   943
sl@0
   944
		case ECmdSendStatus:
sl@0
   945
			// R1 response so status return as for any other R1 command.
sl@0
   946
			if (cmd.iSpec.iCommandClass == KMMCCmdClassApplication)
sl@0
   947
				{
sl@0
   948
				__ASSERT_DEBUG(
sl@0
   949
					iCardInfo[targetCard]->iIsSDCard,
sl@0
   950
					DWinsSDIOStack::Panic(DWinsSDIOStack::EStkICMACMD13NotSD));
sl@0
   951
sl@0
   952
				memset(cmd.iDataMemoryP, 0, KSDStatusBlockLength);
sl@0
   953
				if (iCardInfo[targetCard]->iBusWidth == 1)
sl@0
   954
					cmd.iDataMemoryP[0] = 0x00 << 6;
sl@0
   955
				else	// if (iCardInfo[targetCard]->iBusWidth == 4)
sl@0
   956
					cmd.iDataMemoryP[0] = 0x02 << 6;
sl@0
   957
				cmd.iDataMemoryP[7] = 0x28;		// PROTECTED_AREA_SIZE
sl@0
   958
				}
sl@0
   959
			break;
sl@0
   960
sl@0
   961
		case ECmdReadSingleBlock:
sl@0
   962
		case ECmdReadMultipleBlock:
sl@0
   963
			{
sl@0
   964
			winHandle=iCardInfo[targetCard]->iAreaHandles[KSDUserArea];
sl@0
   965
sl@0
   966
			if ( cmd.iSpec.iUseStopTransmission && cmd.iBlockLength >= cmd.iTotalLength)
sl@0
   967
				return( KMMCErrNotSupported );
sl@0
   968
sl@0
   969
    		TMMCErr err;
sl@0
   970
			TInt pos = cmd.iArgument;
sl@0
   971
    		if (SetFilePointer(winHandle,pos,NULL,FILE_BEGIN)==0xffffffffu)
sl@0
   972
        		err=MapLastErrorMmc();
sl@0
   973
    		else
sl@0
   974
        		{
sl@0
   975
	    		DWORD res;
sl@0
   976
				TInt len = cmd.iTotalLength;
sl@0
   977
		        if (ReadFile(winHandle,(TAny*)cmd.iDataMemoryP,len,&res,NULL)==FALSE)
sl@0
   978
                    err=MapLastErrorMmc();
sl@0
   979
                else if (res!=(DWORD)len)
sl@0
   980
                    err=KMMCErrGeneral;
sl@0
   981
                else
sl@0
   982
                    err=KMMCErrNone;
sl@0
   983
				}
sl@0
   984
			if (err!=KMMCErrNone)
sl@0
   985
				return(err);
sl@0
   986
			break;
sl@0
   987
			}
sl@0
   988
sl@0
   989
		case ECmd22:
sl@0
   990
			if (cmd.iSpec.iCommandClass == KMMCCmdClassApplication)
sl@0
   991
				{
sl@0
   992
				TMMC::BigEndian4Bytes(cmd.iResponse, iMBWOKBlocks);
sl@0
   993
				}
sl@0
   994
			break;
sl@0
   995
		// ------------------------------------------------------------------
sl@0
   996
		case ECmdWriteBlock:
sl@0
   997
		case ECmdWriteMultipleBlock:
sl@0
   998
			{
sl@0
   999
			TUint32 writeLen;
sl@0
  1000
sl@0
  1001
			// periodically fail multi-block writes to test ACMD22 error recovery
sl@0
  1002
			if (cmd.iCommand != ECmdWriteMultipleBlock)
sl@0
  1003
				writeLen = cmd.iTotalLength;
sl@0
  1004
			else
sl@0
  1005
				{
sl@0
  1006
				const TInt KMaxFailCnt = 4;
sl@0
  1007
				static TInt failCnt = 0;
sl@0
  1008
				const TInt KMaxFailBlock = 4;
sl@0
  1009
				static TInt failBlocks = 0;
sl@0
  1010
				
sl@0
  1011
				failCnt = (failCnt + 1) % KMaxFailCnt;
sl@0
  1012
				if (failCnt != 0)
sl@0
  1013
					writeLen = cmd.iTotalLength;
sl@0
  1014
				else
sl@0
  1015
					{
sl@0
  1016
					failBlocks = (failBlocks + 1) % KMaxFailBlock;
sl@0
  1017
					
sl@0
  1018
					// fail at least one block
sl@0
  1019
					TInt totalBlocks = cmd.iTotalLength / cmd.iBlockLength;
sl@0
  1020
					TInt blocksToFail = Min(failBlocks + 1, totalBlocks);	// fail at least one block
sl@0
  1021
					iMBWOKBlocks = (totalBlocks - blocksToFail);
sl@0
  1022
					writeLen = iMBWOKBlocks * cmd.iBlockLength;
sl@0
  1023
					if (writeLen == 0)
sl@0
  1024
						return KMMCErrDataTimeOut;
sl@0
  1025
					}
sl@0
  1026
				}
sl@0
  1027
			
sl@0
  1028
			HANDLE h=iCardInfo[targetCard]->iAreaHandles[KSDUserArea];
sl@0
  1029
sl@0
  1030
    		TMMCErr err;
sl@0
  1031
			TInt pos = cmd.iArgument;
sl@0
  1032
    		if (SetFilePointer(h, pos, NULL, FILE_BEGIN)==0xffffffffu)
sl@0
  1033
        		err = MapLastErrorMmc();
sl@0
  1034
    		else
sl@0
  1035
        		{
sl@0
  1036
	    		DWORD res;
sl@0
  1037
				if (! WriteFile(h, (LPCVOID)cmd.iDataMemoryP,writeLen,&res,NULL))
sl@0
  1038
                    err=MapLastErrorMmc();
sl@0
  1039
                else if (res!=(DWORD)writeLen)
sl@0
  1040
                    err=KMMCErrGeneral;
sl@0
  1041
                else
sl@0
  1042
                    err=KMMCErrNone;
sl@0
  1043
				}
sl@0
  1044
sl@0
  1045
			if (err!=KMMCErrNone)
sl@0
  1046
				return(err);
sl@0
  1047
			if (writeLen != cmd.iTotalLength)
sl@0
  1048
				return KMMCErrDataTimeOut;
sl@0
  1049
			}
sl@0
  1050
			break;
sl@0
  1051
sl@0
  1052
		case ECmdAppCmd:
sl@0
  1053
			// targetCard == -1 when ACMD41 being sent because not yet supplied
sl@0
  1054
			if (iAddressedCard != KBroadcastToAllCards)
sl@0
  1055
				{
sl@0
  1056
				// timeout if addressed card is not SD
sl@0
  1057
				if (! iCardInfo[iAddressedCard]->iIsSDCard)
sl@0
  1058
					rto = ETrue;
sl@0
  1059
				}
sl@0
  1060
			else
sl@0
  1061
				{
sl@0
  1062
				// request sent to specific non-SD card
sl@0
  1063
				if (targetCard != -1 && ! iCardInfo[targetCard]->iIsSDCard)
sl@0
  1064
					rto = ETrue;
sl@0
  1065
				}
sl@0
  1066
			break;
sl@0
  1067
sl@0
  1068
		case ECmdSendCSD:
sl@0
  1069
			{
sl@0
  1070
			iCardInfo[targetCard]->GetCSD(cmd.iResponse);
sl@0
  1071
			break;
sl@0
  1072
			}
sl@0
  1073
sl@0
  1074
		// ------------------------------------------------------------------
sl@0
  1075
		case ECmdLockUnlock:
sl@0
  1076
			// in EPOC, Lock() does not actually lock the card.  It just sets the
sl@0
  1077
			// password.  This means that the card is still accessible to the user,
sl@0
  1078
			// but must be unlocked the next time it is powered up.
sl@0
  1079
sl@0
  1080
			// a real card will transiently go into rcv and prg state while processing
sl@0
  1081
			// this command.  When finished, it will fall back into tran state.
sl@0
  1082
			// The R1 response is sent immediately after CMD42.  CIMReadWriteBlocksSM()
sl@0
  1083
			// sends CMD13 to find out whether or not LOCK_UNLOCK_FAIL was set.
sl@0
  1084
sl@0
  1085
			// the asserts in this case protect against invalid data being sent from the
sl@0
  1086
			// media driver.  A real card would fail these corrupt data blocks.
sl@0
  1087
sl@0
  1088
			{
sl@0
  1089
			const TInt8 cmd_byte(*cmd.iDataMemoryP);
sl@0
  1090
			__ASSERT_DEBUG(										// ensure not CLR_PWD && SET_PWD
sl@0
  1091
				!((cmd_byte & KMMCLockUnlockClrPwd) && (cmd_byte & KMMCLockUnlockSetPwd)),
sl@0
  1092
				DWinsSDIOStack::Panic(DWinsSDIOStack::EWinsMMCCorruptCommand) );
sl@0
  1093
			
sl@0
  1094
			__ASSERT_DEBUG(										// not actually lock a card
sl@0
  1095
				!(cmd_byte & KMMCLockUnlockLockUnlock),
sl@0
  1096
				DWinsSDIOStack::Panic(DWinsSDIOStack::EWinsMMCLockAttempt) );
sl@0
  1097
sl@0
  1098
			if (cmd_byte & KMMCLockUnlockErase)					// ERASE (not supported)
sl@0
  1099
				return KMMCErrNotSupported;
sl@0
  1100
sl@0
  1101
			const TInt8 pwd_len = *(cmd.iDataMemoryP + 1);
sl@0
  1102
			const TPtrC8 pwd(cmd.iDataMemoryP + 2, pwd_len);
sl@0
  1103
sl@0
  1104
			if ((cmd_byte & KMMCLockUnlockClrPwd) != 0)			// CLR_PWD == 1
sl@0
  1105
				{
sl@0
  1106
				__ASSERT_DEBUG(
sl@0
  1107
					pwd_len >= 0 && pwd_len <= KMaxMediaPassword,
sl@0
  1108
					DWinsSDIOStack::Panic(DWinsSDIOStack::EWinsMMCCorruptCommand));
sl@0
  1109
sl@0
  1110
				if (iCardInfo[targetCard]->iIsLocked)						// clear when locked
sl@0
  1111
					nextCMD42Failed = ETrue;
sl@0
  1112
				else														// clear when unlocked
sl@0
  1113
					{
sl@0
  1114
					if (iCardInfo[targetCard]->iPWD->Compare(pwd) != 0)		// clear when unlocked with wrong password
sl@0
  1115
						nextCMD42Failed = ETrue;
sl@0
  1116
					else													// clear when unlocked with right password
sl@0
  1117
						{
sl@0
  1118
						// Clear from password store 
sl@0
  1119
						iCardInfo[targetCard]->iPWD->Zero();
sl@0
  1120
						iCardInfo[targetCard]->iIsLocked = EFalse;
sl@0
  1121
						nextCMD42Failed = EFalse;
sl@0
  1122
						
sl@0
  1123
						// Clear from environment settings
sl@0
  1124
						TInt cardNum=(targetCard==0) ? *Wins::CurrentPBusDevicePtr() : 0; // Can't be -1 at this stage
sl@0
  1125
						SetMediaPasswordEnvironmentVar(MMCSocket()->iSocketNumber,cardNum,*(iCardInfo[targetCard]->iPWD));
sl@0
  1126
						}
sl@0
  1127
					}
sl@0
  1128
				}
sl@0
  1129
			else if ((cmd_byte & KMMCLockUnlockSetPwd) == 0)	// SET_PWD == 0: unlock
sl@0
  1130
				{
sl@0
  1131
				__ASSERT_DEBUG(
sl@0
  1132
					pwd_len >= 0 && pwd_len <= KMaxMediaPassword,
sl@0
  1133
					DWinsSDIOStack::Panic(DWinsSDIOStack::EWinsMMCCorruptCommand) );
sl@0
  1134
				
sl@0
  1135
				if (! iCardInfo[targetCard]->iIsLocked)						// unlock when unlocked
sl@0
  1136
					nextCMD42Failed = ETrue;
sl@0
  1137
				else
sl@0
  1138
					{
sl@0
  1139
					if (iCardInfo[targetCard]->iPWD->Compare(pwd) != 0)		// unlock when locked with wrong password
sl@0
  1140
						nextCMD42Failed = ETrue;
sl@0
  1141
					else													// unlock when locked with right password
sl@0
  1142
						{
sl@0
  1143
						iCardInfo[targetCard]->iIsLocked = EFalse;
sl@0
  1144
						nextCMD42Failed = EFalse;
sl@0
  1145
						}
sl@0
  1146
					}
sl@0
  1147
				}
sl@0
  1148
			else /* ((cmd_byte & KMMCLockUnlockSetPwd) != 0) */	// SET_PWD == 1
sl@0
  1149
				{
sl@0
  1150
				__ASSERT_DEBUG(
sl@0
  1151
					cmd_byte & KMMCLockUnlockSetPwd,
sl@0
  1152
					DWinsSDIOStack::Panic(DWinsSDIOStack::EWinsMMCCorruptCommand) );
sl@0
  1153
sl@0
  1154
				// if pwd_len < iCardInfo[targetCard]->iPWD->Length() then data block must be invalid.
sl@0
  1155
				// This can be caused by bad user input rather than inaccurate formation.
sl@0
  1156
				if (!(	pwd_len >= iCardInfo[targetCard]->iPWD->Length()
sl@0
  1157
					&&	pwd_len <= iCardInfo[targetCard]->iPWD->Length() + KMaxMediaPassword ))
sl@0
  1158
					{
sl@0
  1159
					nextCMD42Failed = ETrue;
sl@0
  1160
					}
sl@0
  1161
				else
sl@0
  1162
					{
sl@0
  1163
					const TInt old_pwd_len = iCardInfo[targetCard]->iPWD->Length();
sl@0
  1164
					TPtrC8 old_pwd(cmd.iDataMemoryP + 2, old_pwd_len);
sl@0
  1165
					TPtrC8 new_pwd(cmd.iDataMemoryP + 2 + old_pwd_len, pwd_len - old_pwd_len);
sl@0
  1166
sl@0
  1167
					// card must not be locked and supplied current password must be correct
sl@0
  1168
					if (iCardInfo[targetCard]->iIsLocked || iCardInfo[targetCard]->iPWD->Compare(old_pwd) != 0)
sl@0
  1169
						nextCMD42Failed = ETrue;
sl@0
  1170
					else
sl@0
  1171
						{
sl@0
  1172
						// Set in password store
sl@0
  1173
						iCardInfo[targetCard]->iPWD->Copy(new_pwd);
sl@0
  1174
						nextCMD42Failed = EFalse;
sl@0
  1175
						
sl@0
  1176
						// Set in environment settings
sl@0
  1177
						TInt cardNum=(targetCard==0) ? *Wins::CurrentPBusDevicePtr() : 0; // Can't be -1 at this stage
sl@0
  1178
						SetMediaPasswordEnvironmentVar(MMCSocket()->iSocketNumber,cardNum,*(iCardInfo[targetCard]->iPWD));
sl@0
  1179
						}
sl@0
  1180
					}
sl@0
  1181
				}	// else /* ((cmd_byte & KMMCLockUnlockSetPwd) != 0) */
sl@0
  1182
			}	// case ECmdLockUnlock
sl@0
  1183
			break;
sl@0
  1184
sl@0
  1185
		// ------------------------------------------------------------------
sl@0
  1186
		case ECmd5:
sl@0
  1187
			{
sl@0
  1188
			if (!iCardInfo[iAddressedCard]->iIsSDCard)
sl@0
  1189
				{
sl@0
  1190
				rto = ETrue;
sl@0
  1191
				}
sl@0
  1192
			else
sl@0
  1193
				{
sl@0
  1194
				// bit31 is set to indicate cards are not still powering up
sl@0
  1195
				TUint32 r5 = 0;
sl@0
  1196
				
sl@0
  1197
				r5 |= KWinsSdioFunctionCount << KSDIOFunctionCountShift;
sl@0
  1198
				r5 |= KWinsSdioMemoryPresent ? KSDIOMemoryPresent : 0;
sl@0
  1199
				r5 |= KMMCWinsCardOCRValue;
sl@0
  1200
				r5 |= KSDIOReady;
sl@0
  1201
sl@0
  1202
				TMMC::BigEndian4Bytes(cmd.iResponse, r5);
sl@0
  1203
				}
sl@0
  1204
			}
sl@0
  1205
			break;
sl@0
  1206
sl@0
  1207
		case ECmd52:
sl@0
  1208
			{
sl@0
  1209
			if (!iCardInfo[iAddressedCard]->iIsSDCard)
sl@0
  1210
				{
sl@0
  1211
				rto = ETrue;
sl@0
  1212
				}
sl@0
  1213
			else
sl@0
  1214
				{
sl@0
  1215
				const TUint32 address  = (cmd.iArgument >> KSdioCmdAddressShift)  & KSdioCmdAddressMask;
sl@0
  1216
				const TUint32 function = (cmd.iArgument >> KSdioCmdFunctionShift) & KSdioCmdFunctionMask;
sl@0
  1217
				
sl@0
  1218
				const TUint32 ioAddress = address + (0x100*function);
sl@0
  1219
sl@0
  1220
				const SRegisterMapInfo* entry = NULL;
sl@0
  1221
				entry = FindIoEntryFromAddress(IoMapTop, ioAddress);
sl@0
  1222
				
sl@0
  1223
				if(!entry)
sl@0
  1224
					{
sl@0
  1225
					rto = ETrue;
sl@0
  1226
					}
sl@0
  1227
				else
sl@0
  1228
					{
sl@0
  1229
					if((cmd.iArgument & KSdioCmdDirMask) == KSdioCmdRead)
sl@0
  1230
						{
sl@0
  1231
						TUint8 dataVal = 0;
sl@0
  1232
						if(entry->iAccessFunction)
sl@0
  1233
							{
sl@0
  1234
							entry->iAccessFunction(targetCard, entry->iRegisterID, this, ETrue, dataVal);
sl@0
  1235
							}
sl@0
  1236
						
sl@0
  1237
						if(entry->iDataP)
sl@0
  1238
							{
sl@0
  1239
							TUint entryOffset = ioAddress - entry->iAddress;
sl@0
  1240
							if(entryOffset >= 0 && entryOffset < entry->iLength)
sl@0
  1241
								{
sl@0
  1242
								dataVal = ((TUint8*)entry->iDataP)[entryOffset];
sl@0
  1243
								}
sl@0
  1244
							}
sl@0
  1245
sl@0
  1246
						TUint32 r5 = 0;
sl@0
  1247
sl@0
  1248
						r5 |= dataVal;
sl@0
  1249
						r5 |= 0x1000;
sl@0
  1250
sl@0
  1251
						TMMC::BigEndian4Bytes(cmd.iResponse, r5);
sl@0
  1252
						}
sl@0
  1253
					else
sl@0
  1254
						{
sl@0
  1255
						const TBool raw = (cmd.iArgument & KSdioCmdRAW) ? ETrue : EFalse;
sl@0
  1256
						TUint8 data = (TUint8)(cmd.iArgument & KSdioCmdDataMask);
sl@0
  1257
sl@0
  1258
						if(entry->iDataP)
sl@0
  1259
							{
sl@0
  1260
							*(TUint8*)(entry->iDataP) &= ~(entry->iFlags);
sl@0
  1261
							*(TUint8*)(entry->iDataP) |= (data & entry->iFlags);
sl@0
  1262
							}
sl@0
  1263
						
sl@0
  1264
						if(entry->iAccessFunction)
sl@0
  1265
							{
sl@0
  1266
							entry->iAccessFunction(targetCard, entry->iRegisterID, this, EFalse, data);
sl@0
  1267
							}
sl@0
  1268
						
sl@0
  1269
						TUint32 r5 = 0;
sl@0
  1270
							
sl@0
  1271
						if(raw)
sl@0
  1272
							{
sl@0
  1273
							r5 |= data;
sl@0
  1274
							}
sl@0
  1275
sl@0
  1276
//						r5 |= 0x1000;
sl@0
  1277
						r5 |= 0x2000;
sl@0
  1278
sl@0
  1279
						TMMC::BigEndian4Bytes(cmd.iResponse, r5);
sl@0
  1280
						}			
sl@0
  1281
					}
sl@0
  1282
				}
sl@0
  1283
			}
sl@0
  1284
			break;
sl@0
  1285
sl@0
  1286
		case ECmd53:
sl@0
  1287
			{
sl@0
  1288
			TBool a = EFalse;
sl@0
  1289
			if(a)
sl@0
  1290
				{
sl@0
  1291
				return(KMMCErrDataTimeOut);
sl@0
  1292
				}
sl@0
  1293
sl@0
  1294
			if (!iCardInfo[iAddressedCard]->iIsSDCard)
sl@0
  1295
				{
sl@0
  1296
				rto = ETrue;
sl@0
  1297
				}
sl@0
  1298
			else
sl@0
  1299
				{
sl@0
  1300
				const TUint32 address  = (cmd.iArgument >> KSdioCmdAddressShift)  & KSdioCmdAddressMask;
sl@0
  1301
				const TUint32 function = (cmd.iArgument >> KSdioCmdFunctionShift) & KSdioCmdFunctionMask;
sl@0
  1302
				
sl@0
  1303
				const TUint32 ioAddress = address + (0x100*function);
sl@0
  1304
sl@0
  1305
				if((cmd.iArgument & KSdioCmdBlockMode) == KSdioCmdBlockMode)
sl@0
  1306
					{
sl@0
  1307
					// Block mode not supported (yet)
sl@0
  1308
					rto = ETrue;
sl@0
  1309
					}
sl@0
  1310
				else
sl@0
  1311
					{
sl@0
  1312
					TUint32 byteCount = cmd.iArgument & KSdioCmdCountMask;
sl@0
  1313
					TUint32 count = 0;
sl@0
  1314
					TUint32 currentAddress = ioAddress;
sl@0
  1315
sl@0
  1316
					TUint32 inc = ((cmd.iArgument & KSdioCmdAutoInc) == KSdioCmdAutoInc) ? 1 : 0;
sl@0
  1317
		
sl@0
  1318
					while(count < byteCount)
sl@0
  1319
						{
sl@0
  1320
						const SRegisterMapInfo* entry = NULL;
sl@0
  1321
						entry = FindIoEntryFromAddress(IoMapTop, currentAddress);
sl@0
  1322
sl@0
  1323
						if(entry)
sl@0
  1324
							{
sl@0
  1325
							if((cmd.iArgument & KSdioCmdDirMask) == KSdioCmdRead)
sl@0
  1326
								{
sl@0
  1327
								TUint8 dataVal = 0;
sl@0
  1328
								if(entry->iAccessFunction)
sl@0
  1329
									{
sl@0
  1330
									entry->iAccessFunction(targetCard, entry->iRegisterID, this, ETrue, dataVal);
sl@0
  1331
									}
sl@0
  1332
								
sl@0
  1333
								if(entry->iDataP)
sl@0
  1334
									{
sl@0
  1335
									TUint entryOffset = currentAddress - entry->iAddress;
sl@0
  1336
									if(entryOffset >= 0 && entryOffset < entry->iLength)
sl@0
  1337
										{
sl@0
  1338
										dataVal = ((TUint8*)entry->iDataP)[entryOffset];
sl@0
  1339
										}
sl@0
  1340
									}
sl@0
  1341
sl@0
  1342
								cmd.iDataMemoryP[count] = dataVal;
sl@0
  1343
								}
sl@0
  1344
							else
sl@0
  1345
								{
sl@0
  1346
								TUint8 data = cmd.iDataMemoryP[count];
sl@0
  1347
sl@0
  1348
								if(entry->iDataP)
sl@0
  1349
									{
sl@0
  1350
									TUint entryOffset = currentAddress - entry->iAddress;
sl@0
  1351
									if(entryOffset >= 0 && entryOffset < entry->iLength)
sl@0
  1352
										{
sl@0
  1353
										((TUint8*)entry->iDataP)[entryOffset] &= ~(entry->iFlags);
sl@0
  1354
										((TUint8*)entry->iDataP)[entryOffset] |= (data & entry->iFlags);
sl@0
  1355
										}
sl@0
  1356
sl@0
  1357
									}
sl@0
  1358
								
sl@0
  1359
								if(entry->iAccessFunction)
sl@0
  1360
									{
sl@0
  1361
									entry->iAccessFunction(targetCard, entry->iRegisterID, this, EFalse, data);
sl@0
  1362
									}								
sl@0
  1363
								}			
sl@0
  1364
							}
sl@0
  1365
							
sl@0
  1366
							count++;
sl@0
  1367
							currentAddress += inc;
sl@0
  1368
						}
sl@0
  1369
sl@0
  1370
						TUint32 r5 = 0;
sl@0
  1371
						
sl@0
  1372
//						r5 |= 0x2000;
sl@0
  1373
						r5 |= 0x1000;
sl@0
  1374
sl@0
  1375
						TMMC::BigEndian4Bytes(cmd.iResponse, r5);
sl@0
  1376
					}
sl@0
  1377
				}
sl@0
  1378
			}
sl@0
  1379
			break;
sl@0
  1380
sl@0
  1381
		// ------------------------------------------------------------------
sl@0
  1382
		default:
sl@0
  1383
			break;
sl@0
  1384
		}
sl@0
  1385
sl@0
  1386
	if (rto)
sl@0
  1387
		return(KMMCErrResponseTimeOut);
sl@0
  1388
sl@0
  1389
	cmd.iCommand = origCmd;
sl@0
  1390
	// If this is an R1 or R1b response type command then return card status as a response
sl@0
  1391
	if (	targetCard != -1
sl@0
  1392
		&&	(cmd.iSpec.iResponseType==ERespTypeR1 || cmd.iSpec.iResponseType==ERespTypeR1B) )
sl@0
  1393
		{
sl@0
  1394
		TUint32 resp(
sl@0
  1395
				iCardInfo[targetCard]->iState
sl@0
  1396
			|	((iCardInfo[targetCard]->iIsLocked ? 1 : 0) << 25)
sl@0
  1397
			|	((lock_unlock_failed ? 1 : 0) << 24) );
sl@0
  1398
sl@0
  1399
		if (iCMD42Failed)								// previous CMD42
sl@0
  1400
			{
sl@0
  1401
			resp |= KMMCStatErrLockUnlock;
sl@0
  1402
			nextCMD42Failed = EFalse;
sl@0
  1403
			}
sl@0
  1404
		iCMD42Failed = nextCMD42Failed;
sl@0
  1405
		TMMC::BigEndian4Bytes(&cmd.iResponse[0],resp); // Ignore bits 47-40
sl@0
  1406
		}
sl@0
  1407
	SMF_END
sl@0
  1408
	}
sl@0
  1409
sl@0
  1410
TInt DWinsSDIOStack::AccessIoEnable(TInt /*aTargetCard*/, TInt /*aVal*/, TAny* aSelfP, TBool aRead, TUint8& aData)
sl@0
  1411
//
sl@0
  1412
// Access the IO Enable register
sl@0
  1413
//
sl@0
  1414
	{
sl@0
  1415
	DWinsSDIOStack& self = *(DWinsSDIOStack*)aSelfP;
sl@0
  1416
	
sl@0
  1417
	if(aRead)
sl@0
  1418
		{
sl@0
  1419
		aData = GCCCRRegIoEnable;
sl@0
  1420
		}
sl@0
  1421
	else
sl@0
  1422
		{
sl@0
  1423
		TUint8 mask = 0;
sl@0
  1424
		for(TInt i=0; i<KWinsSdioFunctionCount; i++)
sl@0
  1425
			{
sl@0
  1426
			mask |= (0x02 << i);
sl@0
  1427
			}
sl@0
  1428
sl@0
  1429
		aData &= mask;
sl@0
  1430
sl@0
  1431
		// Disable functions first...
sl@0
  1432
		GFunctionToEnable &= aData;
sl@0
  1433
		GCCCRRegIoReady   &= aData;
sl@0
  1434
		GCCCRRegIoEnable  &= aData;
sl@0
  1435
		
sl@0
  1436
		// Enabling any functions - This uses the delayed timer...
sl@0
  1437
		if((GCCCRRegIoEnable & aData) != aData)
sl@0
  1438
			{
sl@0
  1439
			GFunctionToEnable = GCCCRRegIoEnable ^ aData;
sl@0
  1440
			GCCCRRegIoEnable |= GFunctionToEnable;
sl@0
  1441
sl@0
  1442
			self.iEnableTimer.OneShot(KFunctionEnableDelay_uS / NKern::TickPeriod());
sl@0
  1443
			}
sl@0
  1444
		}
sl@0
  1445
sl@0
  1446
	return(KErrNone);
sl@0
  1447
	}
sl@0
  1448
sl@0
  1449
void DWinsSDIOStack::EnableTimerCallback(TAny* /*aSelfP*/)
sl@0
  1450
	{
sl@0
  1451
	GCCCRRegIoReady |= GFunctionToEnable;
sl@0
  1452
	}
sl@0
  1453
sl@0
  1454
TInt DWinsSDIOStack::AccessCsaWindow(TInt aTargetCard, TInt /*aVal*/, TAny* aSelfP, TBool aRead, TUint8& aData)
sl@0
  1455
//
sl@0
  1456
// Access the CSA Windoe
sl@0
  1457
//
sl@0
  1458
	{
sl@0
  1459
	TMMCErr err = KErrNone;
sl@0
  1460
sl@0
  1461
	DWinsSDIOStack& self = *(DWinsSDIOStack*)aSelfP;
sl@0
  1462
	
sl@0
  1463
	HANDLE winHandle = self.iCardInfo[aTargetCard]->iAreaHandles[KSDIOArea];
sl@0
  1464
sl@0
  1465
    if (SetFilePointer(winHandle, GFBR1RegCsaPtr, NULL,FILE_BEGIN) == 0xffffffffu)
sl@0
  1466
        err = MapLastErrorMmc();
sl@0
  1467
    else
sl@0
  1468
        {
sl@0
  1469
	    DWORD res;
sl@0
  1470
		TUint8 val = 0;
sl@0
  1471
		TUint len = 1;
sl@0
  1472
		
sl@0
  1473
		BOOL rwRes = FALSE;
sl@0
  1474
sl@0
  1475
		if(aRead)
sl@0
  1476
			{
sl@0
  1477
			rwRes = ReadFile(winHandle, (TAny*)&val, len, &res, NULL);
sl@0
  1478
			}
sl@0
  1479
		else
sl@0
  1480
			{
sl@0
  1481
			val = aData;
sl@0
  1482
			rwRes = WriteFile(winHandle, (TAny*)&val, len, &res, NULL);
sl@0
  1483
			}
sl@0
  1484
sl@0
  1485
		if(rwRes == FALSE)
sl@0
  1486
			{
sl@0
  1487
            err = MapLastErrorMmc();
sl@0
  1488
			}
sl@0
  1489
        else if(res != len)
sl@0
  1490
			{
sl@0
  1491
            err = KMMCErrGeneral;
sl@0
  1492
			}
sl@0
  1493
        else
sl@0
  1494
			{
sl@0
  1495
			if(aRead)
sl@0
  1496
				{
sl@0
  1497
				aData = val;
sl@0
  1498
				}
sl@0
  1499
sl@0
  1500
			GFBR1RegCsaPtr++;
sl@0
  1501
            err = KMMCErrNone;
sl@0
  1502
			}
sl@0
  1503
		}
sl@0
  1504
sl@0
  1505
	return(err);
sl@0
  1506
	}
sl@0
  1507
sl@0
  1508
TInt DWinsSDIOStack::AccessCsaPointer(TInt /*aTargetCard*/, TInt aVal, TAny* /*aSelfP*/, TBool aRead, TUint8& aData)
sl@0
  1509
//
sl@0
  1510
// Access the CSA Windoe
sl@0
  1511
//
sl@0
  1512
	{
sl@0
  1513
	TInt err = KErrNone;
sl@0
  1514
sl@0
  1515
	TUint32 mask  = 0;
sl@0
  1516
	TUint32 shift = 0;
sl@0
  1517
sl@0
  1518
	switch(aVal)
sl@0
  1519
		{
sl@0
  1520
		case KFBRRegCsaPtrLo:
sl@0
  1521
			{
sl@0
  1522
			mask  = 0x0000FF;
sl@0
  1523
			shift = 0;
sl@0
  1524
			break;
sl@0
  1525
			}
sl@0
  1526
sl@0
  1527
		case KFBRRegCsaPtrMid:
sl@0
  1528
			{
sl@0
  1529
			mask  = 0x00FF00;
sl@0
  1530
			shift = 8;
sl@0
  1531
			break;
sl@0
  1532
			}
sl@0
  1533
sl@0
  1534
		case KFBRRegCsaPtrHi:
sl@0
  1535
			{
sl@0
  1536
			mask  = 0xFF0000;
sl@0
  1537
			shift = 16;
sl@0
  1538
			break;
sl@0
  1539
			}
sl@0
  1540
sl@0
  1541
		default:
sl@0
  1542
			{
sl@0
  1543
			err = KErrNotSupported;
sl@0
  1544
			break;
sl@0
  1545
			}
sl@0
  1546
		}
sl@0
  1547
sl@0
  1548
	if(err == KErrNone)
sl@0
  1549
		{
sl@0
  1550
		if(aRead)
sl@0
  1551
			{
sl@0
  1552
			aData = (TUint8)((GFBR1RegCsaPtr & mask) >> shift);
sl@0
  1553
			}
sl@0
  1554
		else
sl@0
  1555
			{
sl@0
  1556
			GFBR1RegCsaPtr &= ~mask;
sl@0
  1557
			GFBR1RegCsaPtr |= (TUint32)aData << shift;
sl@0
  1558
			}
sl@0
  1559
		}
sl@0
  1560
	
sl@0
  1561
	return(err);
sl@0
  1562
	}
sl@0
  1563
sl@0
  1564
void DWinsSDIOStack::EnableSDIOInterrupt(TBool /*aEnable*/)
sl@0
  1565
//
sl@0
  1566
// Virtual
sl@0
  1567
//
sl@0
  1568
	{
sl@0
  1569
	}
sl@0
  1570
sl@0
  1571
void DWinsSDIOStack::SetBusWidth(TUint32 /*aBusWidth*/)
sl@0
  1572
//
sl@0
  1573
// Virtual
sl@0
  1574
//
sl@0
  1575
	{
sl@0
  1576
	}
sl@0
  1577
sl@0
  1578
TUint32 DWinsSDIOStack::MaxBlockSize() const
sl@0
  1579
//
sl@0
  1580
// Virtual
sl@0
  1581
//
sl@0
  1582
	{
sl@0
  1583
	return(512);
sl@0
  1584
	}
sl@0
  1585
sl@0
  1586
sl@0
  1587
TInt DWinsSDIOStack::FindAnyCardInStack(TMMCardStateEnum aState)
sl@0
  1588
//
sl@0
  1589
// first first active card in supplied state.  Return -1 if
sl@0
  1590
// no active card is in supplied state.
sl@0
  1591
//
sl@0
  1592
	{
sl@0
  1593
	if (iAddressedCard != KBroadcastToAllCards)
sl@0
  1594
		return (iCardInfo[iAddressedCard]->iState == aState) ? iAddressedCard : -1;
sl@0
  1595
	else
sl@0
  1596
		{
sl@0
  1597
		for (TInt i = 0; i < KTotalWinsCardSlots; ++i)
sl@0
  1598
			{
sl@0
  1599
			if (iCardInfo[i]->iState == aState)
sl@0
  1600
				return i;
sl@0
  1601
			}
sl@0
  1602
sl@0
  1603
		return -1;
sl@0
  1604
		}
sl@0
  1605
	}
sl@0
  1606
sl@0
  1607
TInt DWinsSDIOStack::FindFirstCardInStack(TMMCardStateEnum aState)
sl@0
  1608
//
sl@0
  1609
// find card which is active on bus and in supplied state.
sl@0
  1610
// There can be more than one active card in the the supplied state,
sl@0
  1611
// but there should be at least one.
sl@0
  1612
//
sl@0
  1613
	{
sl@0
  1614
	if (iAddressedCard != KBroadcastToAllCards)
sl@0
  1615
		{
sl@0
  1616
		__ASSERT_DEBUG(iCardInfo[iAddressedCard]->iState == aState, DWinsSDIOStack::Panic(DWinsSDIOStack::EStkFFCNotSelCard));
sl@0
  1617
		return iAddressedCard;
sl@0
  1618
		}
sl@0
  1619
	else
sl@0
  1620
		{
sl@0
  1621
		TInt idx = -1;
sl@0
  1622
		for (TInt i = 0; idx != -1 && i < KTotalWinsCardSlots; ++i)
sl@0
  1623
			{
sl@0
  1624
			if (iCardInfo[i]->iState == aState)
sl@0
  1625
				idx = i;
sl@0
  1626
			}
sl@0
  1627
sl@0
  1628
		__ASSERT_DEBUG(idx != -1, DWinsSDIOStack::Panic(DWinsSDIOStack::EStkFFCNoneSel));
sl@0
  1629
		return idx;
sl@0
  1630
		}
sl@0
  1631
	}
sl@0
  1632
sl@0
  1633
TInt DWinsSDIOStack::FindOneCardInStack(TMMCardStateEnum aState)
sl@0
  1634
//
sl@0
  1635
// find card which is active on bus and in supplied state.
sl@0
  1636
// There should be exactly one active card in the supplied state.
sl@0
  1637
//
sl@0
  1638
	{
sl@0
  1639
	if (iAddressedCard != KBroadcastToAllCards)
sl@0
  1640
		{
sl@0
  1641
		__ASSERT_DEBUG(iCardInfo[iAddressedCard]->iState == aState, DWinsSDIOStack::Panic(DWinsSDIOStack::EStkFOCNotSelCard));
sl@0
  1642
		return iAddressedCard;
sl@0
  1643
		}
sl@0
  1644
	else
sl@0
  1645
		{
sl@0
  1646
		TInt idx = -1;
sl@0
  1647
		for (TInt i = 0; i < KTotalWinsCardSlots; ++i)
sl@0
  1648
			{
sl@0
  1649
			if (iCardInfo[i]->iState == aState)
sl@0
  1650
				{
sl@0
  1651
				__ASSERT_DEBUG(idx == -1, DWinsSDIOStack::Panic(DWinsSDIOStack::EStkFOCMultiSel));
sl@0
  1652
				idx = i;
sl@0
  1653
				}
sl@0
  1654
			}
sl@0
  1655
sl@0
  1656
		__ASSERT_DEBUG(idx != -1, DWinsSDIOStack::Panic(DWinsSDIOStack::EStkFOCNoneSel));
sl@0
  1657
		return idx;
sl@0
  1658
		}
sl@0
  1659
	}
sl@0
  1660
sl@0
  1661
sl@0
  1662
// ======== DWinsMMCMediaChange ========
sl@0
  1663
sl@0
  1664
#pragma warning( disable : 4355 )	// this used in initializer list
sl@0
  1665
DWinsMMCMediaChange::DWinsMMCMediaChange(TInt aMediaChangeNum)
sl@0
  1666
	: DMMCMediaChange(aMediaChangeNum),
sl@0
  1667
      iDoorClosedCount(0),
sl@0
  1668
	  iMediaChangeEnable(ETrue),
sl@0
  1669
	  iStackP(NULL)
sl@0
  1670
	{
sl@0
  1671
	iMediaDoorCloseReload=2; 	// Units: In theory-20ms, Actual-100ms
sl@0
  1672
	}
sl@0
  1673
#pragma warning( default : 4355 )
sl@0
  1674
sl@0
  1675
TInt DWinsMMCMediaChange::Create()
sl@0
  1676
//
sl@0
  1677
// Initialiser.
sl@0
  1678
//
sl@0
  1679
	{	
sl@0
  1680
	return(DMediaChangeBase::Create());
sl@0
  1681
	}
sl@0
  1682
sl@0
  1683
void DWinsMMCMediaChange::DoorOpenService()
sl@0
  1684
//
sl@0
  1685
// Handle the media change (this function, never postponed is called on media
sl@0
  1686
// change interrupt). 
sl@0
  1687
//
sl@0
  1688
	{
sl@0
  1689
	Disable();		// Disable interrupt until door closes again.
sl@0
  1690
	iDoorOpenDfc.Enque();
sl@0
  1691
	}
sl@0
  1692
sl@0
  1693
void DWinsMMCMediaChange::DoDoorOpen()
sl@0
  1694
//
sl@0
  1695
// Handle media door open (called on media door open interrupt). 
sl@0
  1696
//
sl@0
  1697
	{
sl@0
  1698
	iDoorClosedCount=iMediaDoorCloseReload;
sl@0
  1699
	// Just start a ticklink to poll for door closing
sl@0
  1700
	iTickLink.Periodic(KMediaChangeTickInterval,DWinsMMCMediaChange::Tick,this);
sl@0
  1701
    }
sl@0
  1702
sl@0
  1703
void DWinsMMCMediaChange::DoDoorClosed()
sl@0
  1704
//
sl@0
  1705
// Handle media door closing (called on media door open interrupt).
sl@0
  1706
//
sl@0
  1707
	{
sl@0
  1708
sl@0
  1709
	iTickLink.Cancel();	// Doesn't matter if wasn't enabled
sl@0
  1710
	Enable();	// Re-enable door interrupts
sl@0
  1711
sl@0
  1712
	// While the door was open the user may have changed the card in slot 0
sl@0
  1713
	if (iStackP && *Wins::CurrentPBusDevicePtr()>=0)
sl@0
  1714
		iStackP->iCardInfo[0]=iStackP->iCardPool[*Wins::CurrentPBusDevicePtr()];
sl@0
  1715
	}
sl@0
  1716
sl@0
  1717
void DWinsMMCMediaChange::ForceMediaChange()
sl@0
  1718
//
sl@0
  1719
// Force media change
sl@0
  1720
//
sl@0
  1721
	{
sl@0
  1722
	DoorOpenService();
sl@0
  1723
	}
sl@0
  1724
sl@0
  1725
TMediaState DWinsMMCMediaChange::MediaState()
sl@0
  1726
//
sl@0
  1727
// Return status of media changed signal.
sl@0
  1728
//
sl@0
  1729
	{
sl@0
  1730
sl@0
  1731
	if (iDoorClosedCount>0)
sl@0
  1732
		return(EDoorOpen);
sl@0
  1733
	return( (*Wins::MediaDoorOpenPtr())?EDoorOpen:EDoorClosed);
sl@0
  1734
	}
sl@0
  1735
sl@0
  1736
void DWinsMMCMediaChange::Tick(TAny *aPtr)
sl@0
  1737
//
sl@0
  1738
// Called on the tick to poll for door closing (called on DFC).
sl@0
  1739
//
sl@0
  1740
	{
sl@0
  1741
sl@0
  1742
	((DWinsMMCMediaChange*)aPtr)->TickService();
sl@0
  1743
	}
sl@0
  1744
sl@0
  1745
void DWinsMMCMediaChange::TickService()
sl@0
  1746
//
sl@0
  1747
// Called on the tick to poll for door closing (called on DFC).
sl@0
  1748
//
sl@0
  1749
	{
sl@0
  1750
sl@0
  1751
	__ASSERT_DEBUG(iDoorClosedCount>=0,DWinsSDIOStack::Panic(DWinsSDIOStack::EWinsMMCMediaChangeTickFault));
sl@0
  1752
	if (!(*Wins::MediaDoorOpenPtr()))
sl@0
  1753
		{
sl@0
  1754
		if (iDoorClosedCount > 0)
sl@0
  1755
			iDoorClosedCount--;
sl@0
  1756
		if (iDoorClosedCount == 0)
sl@0
  1757
			DoorClosedService();
sl@0
  1758
		}
sl@0
  1759
	else
sl@0
  1760
		iDoorClosedCount=iMediaDoorCloseReload; // Door open so start again.
sl@0
  1761
	}
sl@0
  1762
sl@0
  1763
void DWinsMMCMediaChange::Enable()
sl@0
  1764
//
sl@0
  1765
// Enable media change 
sl@0
  1766
//
sl@0
  1767
	{
sl@0
  1768
sl@0
  1769
	iMediaChangeEnable=ETrue;
sl@0
  1770
	}
sl@0
  1771
sl@0
  1772
void DWinsMMCMediaChange::Disable()
sl@0
  1773
//
sl@0
  1774
// Disable media change
sl@0
  1775
//
sl@0
  1776
	{
sl@0
  1777
sl@0
  1778
	iMediaChangeEnable=EFalse;
sl@0
  1779
	}
sl@0
  1780
sl@0
  1781
void DWinsMMCMediaChange::MediaChangeCallBack(TAny *aPtr)
sl@0
  1782
//
sl@0
  1783
// Static called on media change
sl@0
  1784
//
sl@0
  1785
	{
sl@0
  1786
sl@0
  1787
	DWinsMMCMediaChange* mc=(DWinsMMCMediaChange*)aPtr;
sl@0
  1788
	if (mc!=NULL&&mc->iMediaChangeEnable)
sl@0
  1789
		mc->DoorOpenService();
sl@0
  1790
	}
sl@0
  1791
sl@0
  1792
sl@0
  1793
// ======== TWinsCardInfo ========
sl@0
  1794
sl@0
  1795
void TWinsCardInfo::GetCSD(TUint8* aResp) const
sl@0
  1796
	{
sl@0
  1797
	// Bits 127-96
sl@0
  1798
	TUint32 csd=(0x1<<30); 	/* CSD_STRUCTURE: CSD Version No 1.1 */
sl@0
  1799
	csd|=		(0x2<<26); 	/* SPEC_VERS: Version 2.1 */
sl@0
  1800
	csd|=		(0x0E<<16);	/* TAAC: 1mS */  
sl@0
  1801
	csd|=		(0x0A<<8);	/* NSAC: 1000 */  
sl@0
  1802
	csd|=		(0x59);		/* TRAN_SPEED: 5.0Mbit/s */  
sl@0
  1803
	TMMC::BigEndian4Bytes(&aResp[0],csd);
sl@0
  1804
	// Bits 95-64
sl@0
  1805
	const TUint32 ccc = 
sl@0
  1806
			KMMCCmdClassBasic | KMMCCmdClassBlockRead
sl@0
  1807
		|	KMMCCmdClassBlockWrite | KMMCCmdClassLockCard;
sl@0
  1808
	csd=		(ccc<<20); 	/* CCC: classes 0, 2, 4, and 7 */
sl@0
  1809
	csd|=		(0x9<<16); 	/* READ_BL_LEN: 512 bytes */
sl@0
  1810
	csd|=		(0x0<<15);	/* READ_BL_PARTIAL: No */  
sl@0
  1811
	csd|=		(0x0<<14);	/* WRITE_BLK_MISALIGN: No */  
sl@0
  1812
	csd|=		(0x0<<13);	/* READ_BLK_MISALIGN: No */  
sl@0
  1813
	csd|=		(0x0<<12);	/* DSR_IMP: No DSR */ 
sl@0
  1814
	csd|=		(0x0<<8);	/* C_SIZE: 1Mb */
sl@0
  1815
	csd|=		(0x7F);		/* C_SIZE: 1Mb (cont)*/  
sl@0
  1816
	TMMC::BigEndian4Bytes(&aResp[4],csd); 
sl@0
  1817
	// Bits 63-32
sl@0
  1818
	csd=		(3UL<<30); 	/* C_SIZE: 2Mb (cont) */
sl@0
  1819
	csd|=		(0x1<<27); 	/* VDD_R_CURR_MIN: 1mA */
sl@0
  1820
	csd|=		(0x1<<24);	/* VDD_R_CURR_MAX: 5mA */  
sl@0
  1821
	csd|=		(0x2<<21); 	/* VDD_W_CURR_MIN: 5mA */
sl@0
  1822
	csd|=		(0x3<<18);	/* VDD_W_CURR_MAX: 25mA */  
sl@0
  1823
	csd|=		(0x0<<15);	/* C_SIZE_MULT: 0 */  
sl@0
  1824
	if (! iIsSDCard)
sl@0
  1825
		{
sl@0
  1826
		csd|=		(0x0<<10);	/* SECTOR_SIZE: 1 write block */  
sl@0
  1827
		csd|=		(0x0<<5);	/* ERASE_GRP_SIZE: 1 sector */  
sl@0
  1828
		csd|=		(0x0);		/* WP_GRP_SIZE: 1 erase group */  
sl@0
  1829
		}
sl@0
  1830
	else
sl@0
  1831
		{
sl@0
  1832
		csd |= (0x00 << (46 - 32));	// ERASE_BLK_EN
sl@0
  1833
		csd |= (0x1f << (39 - 32));	// SECTOR_SIZE: 32 write blocks
sl@0
  1834
		csd |= (0x00 << (32 - 32));	// WP_GRP_SIZE: 1 erase sector.
sl@0
  1835
		}
sl@0
  1836
	TMMC::BigEndian4Bytes(&aResp[8],csd); 
sl@0
  1837
	// Bits 31-0
sl@0
  1838
	csd=		(0x0<<31); 	/* WP_GRP_ENABLE: No */
sl@0
  1839
	csd|=		(0x0<<29); 	/* DEFAULT_ECC: ? */
sl@0
  1840
	csd|=		(0x3<<26);	/* R2W_FACTOR: 8 */  
sl@0
  1841
	csd|=		(0x9<<22); 	/* WRITE_BL_LEN: 512 bytes */
sl@0
  1842
	csd|=		(0x0<<21);	/* WRITE_BL_PARTIAL: No */  
sl@0
  1843
	csd|=		(0x0<<15);	/* FILE_FORMAT_GRP: Hard disk */  
sl@0
  1844
	csd|=		(0x0<<14);	/* COPY: original */  
sl@0
  1845
	csd|=		(0x0<<13);	/* PERM_WRITE_PROTECT: No */  
sl@0
  1846
	csd|=		(0x0<<12);	/* TMP_WRITE_PROTECT: No */  
sl@0
  1847
	csd|=		(0x0<<10);	/* FILE_FORMAT: Hard disk */  
sl@0
  1848
	csd|=		(0x0<<8);	/* ECC: None */  
sl@0
  1849
	csd|=		(0x0<<1);	/* CRC: ? */  
sl@0
  1850
	csd|=		(0x1);		/* not used */  
sl@0
  1851
	TMMC::BigEndian4Bytes(&aResp[12],csd);
sl@0
  1852
	}
sl@0
  1853
sl@0
  1854
// ======== DWinsSDIOPsu ========
sl@0
  1855
sl@0
  1856
sl@0
  1857
DWinsSDIOPsu::DWinsSDIOPsu(TInt aVccNum, TInt aMcId)
sl@0
  1858
	: DSDIOPsu(aVccNum, aMcId)
sl@0
  1859
	{}
sl@0
  1860
sl@0
  1861
void DWinsSDIOPsu::Init()
sl@0
  1862
//
sl@0
  1863
// Initialise the PSU
sl@0
  1864
//
sl@0
  1865
    {
sl@0
  1866
	// Nothing to do
sl@0
  1867
    }
sl@0
  1868
sl@0
  1869
void DWinsSDIOPsu::DoSetState(TPBusPsuState aState)
sl@0
  1870
//
sl@0
  1871
// Turn on/off the PSU. If it is possible to adjust the output voltage on this
sl@0
  1872
// PSU then retreive the required voltage level from TMMCPsu::iVoltageSetting
sl@0
  1873
// (which is in OCR register format).
sl@0
  1874
//
sl@0
  1875
    {
sl@0
  1876
sl@0
  1877
    switch (aState)
sl@0
  1878
        {
sl@0
  1879
        case EPsuOff:
sl@0
  1880
            break;
sl@0
  1881
        case EPsuOnFull:
sl@0
  1882
            break;
sl@0
  1883
        case EPsuOnCurLimit:
sl@0
  1884
            break;
sl@0
  1885
        }
sl@0
  1886
    }
sl@0
  1887
sl@0
  1888
TInt DWinsSDIOPsu::VoltageInMilliVolts()
sl@0
  1889
//
sl@0
  1890
// Return the level of the PSU (in mV) or -ve if error.
sl@0
  1891
//
sl@0
  1892
    {
sl@0
  1893
sl@0
  1894
    return(0);
sl@0
  1895
    }
sl@0
  1896
sl@0
  1897
void DWinsSDIOPsu::DoCheckVoltage()
sl@0
  1898
//
sl@0
  1899
// Check the voltage level of the PSU is as expected. Returns either KErrNone, KErrGeneral 
sl@0
  1900
// to indicate the pass/fail state or KErrNotReady if the voltage check isn't complete.
sl@0
  1901
//
sl@0
  1902
    {
sl@0
  1903
sl@0
  1904
	ReceiveVoltageCheckResult(KErrNone);
sl@0
  1905
    }
sl@0
  1906
sl@0
  1907
void DWinsSDIOPsu::PsuInfo(TPBusPsuInfo &anInfo)
sl@0
  1908
//
sl@0
  1909
// Return machine info relating to the MMC PSU supply
sl@0
  1910
//
sl@0
  1911
    {
sl@0
  1912
sl@0
  1913
	anInfo.iVoltageSupported=0x00040000; // 3.0V (OCR reg. format).
sl@0
  1914
	anInfo.iMaxCurrentInMicroAmps=0;
sl@0
  1915
	anInfo.iVoltCheckInterval=0;
sl@0
  1916
	anInfo.iVoltCheckMethod=EPsuChkComparator;
sl@0
  1917
sl@0
  1918
	anInfo.iNotLockedTimeOut=5;
sl@0
  1919
	anInfo.iInactivityTimeOut=10;
sl@0
  1920
    }