os/kernelhwsrv/kernel/eka/drivers/medata/pccd_ata.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) 1996-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 the License "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
// e32\drivers\medata\pccd_ata.cpp
sl@0
    15
// 
sl@0
    16
//
sl@0
    17
sl@0
    18
#include "pbusmedia.h"
sl@0
    19
#include "platform.h"
sl@0
    20
#include "ata.h"
sl@0
    21
sl@0
    22
const TInt KErrBadDrqOnRead=-64;
sl@0
    23
const TInt KErrBadDrqOnWrite=-65;
sl@0
    24
const TInt KErrBadDrq=-66;
sl@0
    25
const TInt KErrAta=-67;
sl@0
    26
const TInt KErrBadPccdConfig=-68;
sl@0
    27
//const TInt KErrDriveChunkNotOpen=-69;
sl@0
    28
sl@0
    29
const TInt KAtaDriverPriority=KMediaDriverPriorityNormal;
sl@0
    30
//const TInt KAtaDriverPriority=KMediaDriverPriorityHigh;
sl@0
    31
sl@0
    32
_LIT(KPddName, "Media.Ata");
sl@0
    33
//_LIT(KPddName, "Media.Ata2");
sl@0
    34
sl@0
    35
// One of these
sl@0
    36
#define SELECT_CONTIGUOUS_IO_CONFIG
sl@0
    37
//#define SELECT_PRIMARY_IO_CONFIG
sl@0
    38
//#define SELECT_MEMORY_CONFIG
sl@0
    39
sl@0
    40
//#define FORCE_8BIT_ACCESSES
sl@0
    41
sl@0
    42
// Special debug options
sl@0
    43
//#define SHOW_CARD_ERRORS
sl@0
    44
//#define DEBUG_WITH_HW_TRIGGER
sl@0
    45
//#define COUNT_TIMEOUTS
sl@0
    46
sl@0
    47
#if (defined(SHOW_CARD_ERRORS))
sl@0
    48
#define __KTRACE_CARD_ERROR(a,p) {p;}
sl@0
    49
#elif (defined(_DEBUG))
sl@0
    50
#define __KTRACE_CARD_ERROR(a,p) {if((KDebugNum(a)))p;}
sl@0
    51
#else
sl@0
    52
#define __KTRACE_CARD_ERROR(a,p)
sl@0
    53
#endif
sl@0
    54
sl@0
    55
#include <pccard.h>
sl@0
    56
sl@0
    57
const TInt KMaxSectorsPerRead=32;
sl@0
    58
const TInt KMaxSectorsPerWrite=8;				 
sl@0
    59
const TInt KMaxSectorsPerFormat=8;				 
sl@0
    60
const TInt KMaxBytesPerRead=(KMaxSectorsPerRead<<KAtaSectorShift);
sl@0
    61
const TInt KMaxBytesPerWrite=(KMaxSectorsPerWrite<<KAtaSectorShift);
sl@0
    62
sl@0
    63
// Sector buffer size must be a multiple of sector size and at least as large
sl@0
    64
// as KMaxSectorsPerWrite.
sl@0
    65
const TInt KSectBufSizeInSectors=8;
sl@0
    66
const TInt KSectBufSizeInBytes=(KSectBufSizeInSectors<<KAtaSectorShift);
sl@0
    67
const TInt KSectBufSizeInBytesMinusOneSector=(KSectBufSizeInBytes-KAtaSectorSize);
sl@0
    68
sl@0
    69
const TInt KIdleCurrentInMilliAmps=1; 
sl@0
    70
const TInt KReadCurrentInMilliAmps=39;
sl@0
    71
const TInt KWriteCurrentInMilliAmps=46;
sl@0
    72
sl@0
    73
const TInt KNotBusySyncTimeout=5;
sl@0
    74
const TInt KNotBusySyncRetryCount=10;
sl@0
    75
const TInt KDriveReadySyncTimeout=5;
sl@0
    76
sl@0
    77
#ifdef _DEBUG
sl@0
    78
const TInt KNotBusyTestInterval=30;		// Check for not-busy once every 30ms
sl@0
    79
const TInt KBusyTimeOut=67;				// Timeout after this many tests (67*30ms=2010ms)
sl@0
    80
#else
sl@0
    81
const TInt KNotBusyTestInterval=5;		// Check for not-busy once every 5ms
sl@0
    82
const TInt KBusyTimeOut=400;			// Timeout after this many tests (400*5ms=2010ms)
sl@0
    83
#endif
sl@0
    84
sl@0
    85
class DPhysicalDeviceMediaAta : public DPhysicalDevice
sl@0
    86
	{
sl@0
    87
public:
sl@0
    88
	DPhysicalDeviceMediaAta();
sl@0
    89
	virtual TInt Install();
sl@0
    90
	virtual void GetCaps(TDes8& aDes) const;
sl@0
    91
	virtual TInt Create(DBase*& aChannel, TInt aMediaId, const TDesC8* anInfo, const TVersion& aVer);
sl@0
    92
	virtual TInt Validate(TInt aDeviceType, const TDesC8* anInfo, const TVersion& aVer);
sl@0
    93
	virtual TInt Info(TInt aFunction, TAny* a1);
sl@0
    94
	};
sl@0
    95
sl@0
    96
class DPcCardMediaDriverAta : public DMediaDriver
sl@0
    97
	{
sl@0
    98
public:
sl@0
    99
	DPcCardMediaDriverAta(TInt aMediaId);
sl@0
   100
	virtual TInt Request(TLocDrvRequest& aRequest);
sl@0
   101
	virtual TInt PartitionInfo(TPartitionInfo& anInfo);
sl@0
   102
	virtual void NotifyPowerDown();
sl@0
   103
	virtual void NotifyEmergencyPowerDown();
sl@0
   104
	virtual void Close();
sl@0
   105
public:
sl@0
   106
	enum TCardStatus {ECardIdle,ECardRead,ECardWrite,ECardFormat};
sl@0
   107
	inline TUint8 AtaRegister8(TUint aReg);
sl@0
   108
	inline void SetAtaRegister8(TUint8 aValue,TUint aReg);
sl@0
   109
	void ModifyAtaRegister8(TUint aClearMask,TUint aSetMask,TUint aReg);
sl@0
   110
	void SelectDrive(TAtaDriveSelect aDrive);
sl@0
   111
	TBool WaitForNotBusy();
sl@0
   112
	TBool DriveReadyForCommand(TInt aDrive);
sl@0
   113
	void SetLbaSectorAddress(TUint aSector);
sl@0
   114
	void SetChsSectorAddress(TUint aSector);
sl@0
   115
	TInt IssueAtaCommand(TUint8 aCmd,TUint aFirstSector,TInt aSectorCount);
sl@0
   116
	TInt EmptySectBufferToTrg(TUint8 *aSrc,TUint aTrgOffset,TInt aLen);
sl@0
   117
	TInt LoadSectBufferFromSrc(TInt aLen, TUint8* aBuf);
sl@0
   118
	TInt LoadSectBufferFromDrive(TAny *aBuf);
sl@0
   119
	TInt EmptySectBufferToDrive(TUint8 *aBuf);
sl@0
   120
	TInt TransferSectBufferFromDrive(TAny *aBuf);
sl@0
   121
	TInt FinishCommand();
sl@0
   122
	TInt CheckForError();
sl@0
   123
	TInt ProcessError(TInt anError);
sl@0
   124
	TInt SectorBoundaryReadCheck(TUint aStartSector,TUint aStartSectOffset,Int64 anEndPos);
sl@0
   125
	TInt SectorRead(TUint aFirstSector,TUint8 *aBuf,TInt aSectorCount=1,TUint8 aCmd=KAtaCmdReadSectors);
sl@0
   126
	TInt CheckDevice(TBool aCheckPower);
sl@0
   127
	TInt InitiateWriteCommand(TUint aFirstSector,TInt aSectorCount,TUint8 *aSectBuffer);
sl@0
   128
	TInt ReadSectorsCommand(TUint aFirstSector,TUint aBufOffset,TInt aLen);
sl@0
   129
	TInt IdentifyDrive();
sl@0
   130
	void DumpIdentifyDriveInfo();
sl@0
   131
	TInt ConfigAutoPowerDown();
sl@0
   132
	TInt Open();
sl@0
   133
	TInt DoOpen();
sl@0
   134
	void DoClose();
sl@0
   135
	void Reset();
sl@0
   136
	TBool CardPoweredDown();
sl@0
   137
	void IncrementSectBufPtr();
sl@0
   138
	static void CardIreqDfcFunction(TAny* aPtr);
sl@0
   139
	static void TimerDfcFunction(TAny* aPtr);
sl@0
   140
	static void AsyncBusyTimerCallBack(TAny* aMediaDriver);
sl@0
   141
	static void SyncBusyTimerCallBack(TAny* aBusyFlag);
sl@0
   142
	static void CardIntCallBack(TAny* aPtr, TInt anId);
sl@0
   143
	TBool DoCardNotBusy(TInt &anErr);
sl@0
   144
	TBool CmdDfc();
sl@0
   145
	TBool DoCmdDfc(TInt &anErr);
sl@0
   146
	void Complete(TInt anError);
sl@0
   147
	TInt Caps(TLocalDriveCapsV6& anInfo);
sl@0
   148
	TInt DoRead();
sl@0
   149
	TInt DoWrite();
sl@0
   150
	TInt DoFormat();
sl@0
   151
	TInt InitiateAsyncRead();
sl@0
   152
	TInt InitiateAsyncWrite();
sl@0
   153
public:
sl@0
   154
	DPcCardSocket* iSocket;
sl@0
   155
	TLocDrvRequest* iCurrentReq;
sl@0
   156
	TPBusCallBack iCardIntCallBack;
sl@0
   157
	RPccdWindow iDriveChunk;
sl@0
   158
	TPccdMemType iMemoryType;
sl@0
   159
	TDriveParameters iDriveInfo;
sl@0
   160
	NTimer iBusyTimeout;
sl@0
   161
	TDfc iCardIreqDfc;
sl@0
   162
	TDfc iTimerDfc;
sl@0
   163
	TInt iNotBusyTickCount;
sl@0
   164
	TInt iCommandError;
sl@0
   165
	TCardStatus iCardStatus;
sl@0
   166
	TUint iCmdInOffset; 	// Progress counter for data received from src device
sl@0
   167
	TUint iCmdOutOffset;	// Progress counter for data delivered to target device
sl@0
   168
	TUint iCmdEndOffset;	// Marks point when transfer associated with command is complete
sl@0
   169
	TUint iCmdLength;		// Transfer length remaining
sl@0
   170
	TUint iNextSector;		// Next sector to transfer
sl@0
   171
	TUint8 *iSectBufPtr;	// Progress counter for tranfering data between card and sector buffer
sl@0
   172
	TUint iSectBufOffset;	// Offset within sector buffer to start of data involved in command (Reads only)
sl@0
   173
	TBool iLastSectorBufUsed;
sl@0
   174
	TUint iHiddenSectors;
sl@0
   175
	TInt iCardFuncNum;
sl@0
   176
	TUint8 iSectorBuf[KSectBufSizeInBytes]; // Keep on 4byte boundary - put this last
sl@0
   177
	TUint8 iLastSectorBuf[KAtaSectorSize];	// Holds last sector data for unaligned write
sl@0
   178
#if (defined(_DEBUG) || defined(SHOW_CARD_ERRORS))
sl@0
   179
	TInt iDbgLastError;
sl@0
   180
	TInt iDbgPos;
sl@0
   181
	TInt iDbgLen;
sl@0
   182
#endif
sl@0
   183
#ifdef COUNT_TIMEOUTS
sl@0
   184
	TInt iInts;
sl@0
   185
	TInt iTimeouts;
sl@0
   186
	TInt iImmediateNotBusy;
sl@0
   187
	TInt iChainedReads;
sl@0
   188
	TInt iChainedWrites;
sl@0
   189
	TBool iNewTimeOut;
sl@0
   190
	TInt iIndex;
sl@0
   191
	TInt iInfo[8];
sl@0
   192
#endif
sl@0
   193
	};
sl@0
   194
sl@0
   195
void DPcCardMediaDriverAta::Complete(TInt anError)
sl@0
   196
	{
sl@0
   197
	__KTRACE_OPT(KFAIL,Kern::Printf("mdrqc %08x %d",iCurrentReq,anError));
sl@0
   198
#ifdef COUNT_TIMEOUTS
sl@0
   199
	if (iNewTimeOut)
sl@0
   200
		{
sl@0
   201
		iNewTimeOut=EFalse;
sl@0
   202
		Kern::Printf("I=%d T=%d M=%d CR=%d CW=%d",iInts,iTimeouts,iImmediateNotBusy,iChainedReads,iChainedWrites);
sl@0
   203
		TInt i;
sl@0
   204
		for (i=0; i<iIndex; i+=2)
sl@0
   205
			Kern::Printf("%d: %08x %08x",i,iInfo[i],iInfo[i+1]);
sl@0
   206
		iIndex=0;
sl@0
   207
		}
sl@0
   208
#endif
sl@0
   209
	TLocDrvRequest* pR=iCurrentReq;
sl@0
   210
	if (pR)
sl@0
   211
		{
sl@0
   212
		iCurrentReq=NULL;
sl@0
   213
		DMediaDriver::Complete(*pR,anError);
sl@0
   214
		}
sl@0
   215
	}
sl@0
   216
sl@0
   217
inline TUint8 DPcCardMediaDriverAta::AtaRegister8(TUint aReg)
sl@0
   218
//
sl@0
   219
// Read from an 8 bit ATA register
sl@0
   220
//
sl@0
   221
	{
sl@0
   222
sl@0
   223
	return iDriveChunk.Read8(aReg);
sl@0
   224
	}
sl@0
   225
sl@0
   226
inline void DPcCardMediaDriverAta::SetAtaRegister8(TUint8 aValue,TUint aReg)
sl@0
   227
//
sl@0
   228
// Write to an 8 bit ATA register
sl@0
   229
//
sl@0
   230
	{
sl@0
   231
sl@0
   232
	iDriveChunk.Write8(aReg,aValue);
sl@0
   233
	}
sl@0
   234
sl@0
   235
void DPcCardMediaDriverAta::ModifyAtaRegister8(TUint aClearMask,TUint aSetMask,TUint aReg)
sl@0
   236
//
sl@0
   237
// Modify an 8 bit ATA register
sl@0
   238
//
sl@0
   239
	{
sl@0
   240
sl@0
   241
	SetAtaRegister8((TUint8)((AtaRegister8(aReg)&(~aClearMask))|aSetMask),aReg);
sl@0
   242
	}
sl@0
   243
sl@0
   244
void DPcCardMediaDriverAta::SelectDrive(TAtaDriveSelect aDrive)
sl@0
   245
//
sl@0
   246
// Modify an 8 bit ATA register
sl@0
   247
//
sl@0
   248
	{
sl@0
   249
sl@0
   250
	ModifyAtaRegister8(KAtaDrvHeadDrive1,(0xA0|aDrive),KAtaSelectDriveHeadRdWr8);
sl@0
   251
	}
sl@0
   252
sl@0
   253
TBool DPcCardMediaDriverAta::WaitForNotBusy()
sl@0
   254
//
sl@0
   255
// Poll busy flag (while card accesses the data buffer and command register). 
sl@0
   256
// 8mS timeout.
sl@0
   257
//
sl@0
   258
	{
sl@0
   259
sl@0
   260
	// Before we start a timed loop, just check it isn't already not busy
sl@0
   261
	__KTRACE_OPT(KPBUSDRV,Kern::Printf("WfnB"));
sl@0
   262
	if (!(AtaRegister8(KAtaStatusRd8)&KAtaStatusBusy))
sl@0
   263
		return(ETrue);
sl@0
   264
#if (defined(_DEBUG) || defined(SHOW_CARD_ERRORS))
sl@0
   265
	TUint c=NKern::TickCount();
sl@0
   266
#endif
sl@0
   267
	volatile TBool timedOut=EFalse;
sl@0
   268
	NTimer busyTimeout(SyncBusyTimerCallBack,(TAny*)&timedOut);
sl@0
   269
	busyTimeout.OneShot(NKern::TimerTicks(KNotBusySyncTimeout));
sl@0
   270
	FOREVER
sl@0
   271
		{
sl@0
   272
		if (!(AtaRegister8(KAtaStatusRd8)&KAtaStatusBusy)||timedOut)
sl@0
   273
			break;
sl@0
   274
		}
sl@0
   275
	if (!timedOut)
sl@0
   276
		busyTimeout.Cancel();
sl@0
   277
	else
sl@0
   278
		{
sl@0
   279
		TInt retry=KNotBusySyncRetryCount;
sl@0
   280
		while ((AtaRegister8(KAtaStatusRd8)&KAtaStatusBusy) && retry)
sl@0
   281
			{
sl@0
   282
			NKern::Sleep(1);
sl@0
   283
			retry--;
sl@0
   284
			}
sl@0
   285
		}
sl@0
   286
	TBool ret=(AtaRegister8(KAtaStatusRd8) & KAtaStatusBusy);
sl@0
   287
#if (defined(_DEBUG) || defined(SHOW_CARD_ERRORS))
sl@0
   288
	c=NKern::TickCount()-c;
sl@0
   289
	if (ret)
sl@0
   290
		{
sl@0
   291
		__KTRACE_CARD_ERROR(KPBUSDRV,Kern::Printf("<Ata:WaitForNotBusy-timeout(%xH) %d ms",AtaRegister8(KAtaStatusRd8),c));
sl@0
   292
 		}
sl@0
   293
	else
sl@0
   294
		{
sl@0
   295
		__KTRACE_CARD_ERROR(KPBUSDRV,Kern::Printf("<Ata:WaitForNotBusy-OK %d ms",c));
sl@0
   296
		}
sl@0
   297
#endif
sl@0
   298
	return(!ret);
sl@0
   299
	}
sl@0
   300
sl@0
   301
TBool DPcCardMediaDriverAta::DriveReadyForCommand(TInt aDrive)
sl@0
   302
//
sl@0
   303
// Wait until selected drive is able to accept a command (5ms timeout).
sl@0
   304
//					
sl@0
   305
	{
sl@0
   306
sl@0
   307
	// Select the drive were waiting on 
sl@0
   308
	SelectDrive((aDrive==1)?ESelectDrive1:ESelectDrive0);
sl@0
   309
	if (!WaitForNotBusy())
sl@0
   310
		return(EFalse);
sl@0
   311
sl@0
   312
	volatile TBool timedOut=EFalse;
sl@0
   313
	NTimer busyTimeout(SyncBusyTimerCallBack,(TAny*)&timedOut);
sl@0
   314
	busyTimeout.OneShot(NKern::TimerTicks(KDriveReadySyncTimeout));
sl@0
   315
	FOREVER
sl@0
   316
		{
sl@0
   317
		if (AtaRegister8(KAtaStatusRd8)&KAtaStatusRdy||timedOut)
sl@0
   318
			break;
sl@0
   319
		}
sl@0
   320
	if (!timedOut)
sl@0
   321
		busyTimeout.Cancel();
sl@0
   322
	TBool ret=(AtaRegister8(KAtaStatusRd8) & KAtaStatusRdy);
sl@0
   323
#if (defined(_DEBUG) || defined(SHOW_CARD_ERRORS))
sl@0
   324
	if (!ret)
sl@0
   325
		__KTRACE_CARD_ERROR(KPBUSDRV,Kern::Printf("<Ata:DriveReadyForCommand-Fail(%xH)",AtaRegister8(KAtaStatusRd8)));
sl@0
   326
#endif
sl@0
   327
	return(ret);
sl@0
   328
	}
sl@0
   329
sl@0
   330
void DPcCardMediaDriverAta::SetLbaSectorAddress(TUint aSector)
sl@0
   331
//
sl@0
   332
// Setup the sector address ATA registers (LBA mode)
sl@0
   333
//
sl@0
   334
	{
sl@0
   335
	__KTRACE_OPT(KPBUSDRV,Kern::Printf(">Ata:SetLbaSectorAddress (LBA: %xH)",aSector));
sl@0
   336
sl@0
   337
	SetAtaRegister8((TUint8)aSector,KAtaLba7_0RdWr8);
sl@0
   338
	SetAtaRegister8((TUint8)(aSector>>8),KAtaLba15_8RdWr8);
sl@0
   339
	SetAtaRegister8((TUint8)(aSector>>16),KAtaLba23_16RdWr8);
sl@0
   340
	TUint8 lba27_24=(TUint8)((aSector>>24)&0x0F);
sl@0
   341
	ModifyAtaRegister8(KAtaDrvHeadLba27_24,(KAtaDrvHeadLbaOn|lba27_24),KAtaSelectDriveHeadRdWr8);
sl@0
   342
	}
sl@0
   343
sl@0
   344
void DPcCardMediaDriverAta::SetChsSectorAddress(TUint aSector)
sl@0
   345
//
sl@0
   346
// Setup the sector address ATA registers (CHS mode)
sl@0
   347
//
sl@0
   348
	{
sl@0
   349
sl@0
   350
	TUint cylinder=0,head=0,sector=1;
sl@0
   351
	if (iDriveInfo.iSectorsPerCylinder>0&&iDriveInfo.iSectorsPerTrack>0)
sl@0
   352
		{
sl@0
   353
		cylinder=aSector/iDriveInfo.iSectorsPerCylinder;
sl@0
   354
		TUint remainder=aSector%iDriveInfo.iSectorsPerCylinder;
sl@0
   355
		head=remainder/iDriveInfo.iSectorsPerTrack;
sl@0
   356
		sector=(remainder%iDriveInfo.iSectorsPerTrack)+1;
sl@0
   357
		}
sl@0
   358
sl@0
   359
	__KTRACE_OPT(KPBUSDRV,Kern::Printf("Ata:SetChsSectorAddress (C: %xH H: %xH S: %xH)",cylinder,head,sector));
sl@0
   360
	SetAtaRegister8((TUint8)sector,KAtaSectorNoRdWr8);
sl@0
   361
	SetAtaRegister8((TUint8)cylinder,KAtaCylinderLowRdWr8);
sl@0
   362
	SetAtaRegister8((TUint8)(cylinder>>8),KAtaCylinderHighRdWr8);
sl@0
   363
	ModifyAtaRegister8((KAtaDrvHeadLbaOn|KAtaDrvHeadLba27_24),((TUint8)(head&0x0F)),KAtaSelectDriveHeadRdWr8);
sl@0
   364
	}
sl@0
   365
sl@0
   366
TInt DPcCardMediaDriverAta::IssueAtaCommand(TUint8 aCmd,TUint aFirstSector,TInt aSectorCount)
sl@0
   367
//
sl@0
   368
// Issue an ATA command (Drive 0 only for now).
sl@0
   369
//
sl@0
   370
	{
sl@0
   371
sl@0
   372
	__KTRACE_OPT(KPBUSDRV,Kern::Printf(">Ata:IssueAtaCommand(C:%x, FS:%x, SC:%x)",aCmd,aFirstSector,aSectorCount));
sl@0
   373
	__KTRACE_OPT(KFAIL,Kern::Printf("A%02x,%d",aCmd,aSectorCount));
sl@0
   374
	if (!WaitForNotBusy())
sl@0
   375
		return(KErrTimedOut);
sl@0
   376
	if (!DriveReadyForCommand(0))
sl@0
   377
		return KErrTimedOut;
sl@0
   378
	
sl@0
   379
	if (aSectorCount==KMaxSectorsPerCmd)
sl@0
   380
		aSectorCount=0;
sl@0
   381
	SetAtaRegister8((TUint8)aSectorCount,KAtaSectorCountRdWr8);
sl@0
   382
	if (iDriveInfo.iSupportsLba)
sl@0
   383
		SetLbaSectorAddress(aFirstSector);
sl@0
   384
	else
sl@0
   385
		SetChsSectorAddress(aFirstSector);
sl@0
   386
	__TRACE_TIMING(0x103);
sl@0
   387
	SetAtaRegister8(aCmd,KAtaCommandWr8);	// Issue the command
sl@0
   388
	Kern::NanoWait(400);					// Busy flag not asserted for 400ns
sl@0
   389
	__KTRACE_OPT(KPBUSDRV,Kern::Printf("<Ata:IssueAtaCommand"));
sl@0
   390
	return(KErrNone);
sl@0
   391
	}
sl@0
   392
sl@0
   393
TInt DPcCardMediaDriverAta::LoadSectBufferFromDrive(TAny *aBuf)
sl@0
   394
//
sl@0
   395
// Read a sector from the ATA card
sl@0
   396
//
sl@0
   397
	{
sl@0
   398
sl@0
   399
	if (!(AtaRegister8(KAtaStatusRd8)&KAtaStatusDrq))
sl@0
   400
		{
sl@0
   401
		__KTRACE_CARD_ERROR(KPBUSDRV,Kern::Printf(">Ata:LoadSectBufferFromDrive-Bad drq(%xH)",AtaRegister8(KAtaStatusRd8)));
sl@0
   402
		return KErrBadDrqOnRead;
sl@0
   403
		}
sl@0
   404
sl@0
   405
	if (__IS_COMMON_MEM(iMemoryType))
sl@0
   406
		iDriveChunk.Read(KAtaDataRdWrWinBase16,aBuf,KAtaSectorSize); // Use 1K window
sl@0
   407
	else if (iMemoryType==EPccdIo16Mem)
sl@0
   408
		iDriveChunk.ReadHWordMultiple(KAtaDataRdWr16,aBuf,(KAtaSectorSize>>1));
sl@0
   409
	else
sl@0
   410
		iDriveChunk.ReadByteMultiple(KAtaDataRdWr8,aBuf,KAtaSectorSize); // Must be EPccdIo8Mem
sl@0
   411
sl@0
   412
	return(KErrNone);
sl@0
   413
	}
sl@0
   414
sl@0
   415
TInt DPcCardMediaDriverAta::TransferSectBufferFromDrive(TAny *aBuf)
sl@0
   416
//
sl@0
   417
// Read a sector from the ATA card
sl@0
   418
//
sl@0
   419
	{
sl@0
   420
sl@0
   421
	if (!WaitForNotBusy())
sl@0
   422
		return(KErrTimedOut);
sl@0
   423
	return(LoadSectBufferFromDrive(aBuf));
sl@0
   424
	}
sl@0
   425
sl@0
   426
TInt DPcCardMediaDriverAta::EmptySectBufferToDrive(TUint8 *aBuf)
sl@0
   427
//
sl@0
   428
// Write a sector to the ATA card.
sl@0
   429
//
sl@0
   430
	{
sl@0
   431
sl@0
   432
	if (!(AtaRegister8(KAtaStatusRd8)&KAtaStatusDrq))
sl@0
   433
		{
sl@0
   434
		__KTRACE_CARD_ERROR(KPBUSDRV,Kern::Printf(">Ata:EmptySectBufferToDrive-Bad drq(%xH)",AtaRegister8(KAtaStatusRd8)));
sl@0
   435
		return KErrBadDrqOnWrite;
sl@0
   436
		}
sl@0
   437
sl@0
   438
	if (__IS_COMMON_MEM(iMemoryType))
sl@0
   439
		iDriveChunk.Write(KAtaDataRdWrWinBase16,aBuf,KAtaSectorSize); // Use 1K window
sl@0
   440
	else if (iMemoryType==EPccdIo16Mem)
sl@0
   441
		iDriveChunk.WriteHWordMultiple(KAtaDataRdWr16,aBuf,(KAtaSectorSize>>1));
sl@0
   442
	else
sl@0
   443
		iDriveChunk.WriteByteMultiple(KAtaDataRdWr8,aBuf,KAtaSectorSize); // Must be EPccdIo8Mem
sl@0
   444
sl@0
   445
	return(KErrNone); 
sl@0
   446
	}
sl@0
   447
sl@0
   448
TInt DPcCardMediaDriverAta::FinishCommand()
sl@0
   449
//
sl@0
   450
// Called each time a command has been issued to check if an error occured.
sl@0
   451
//
sl@0
   452
	{
sl@0
   453
sl@0
   454
	if (!WaitForNotBusy())
sl@0
   455
		return(KErrTimedOut);
sl@0
   456
	return(CheckForError());
sl@0
   457
	}
sl@0
   458
sl@0
   459
TInt DPcCardMediaDriverAta::CheckForError()
sl@0
   460
//
sl@0
   461
// Called each time a command has been issued to check if an error occured.
sl@0
   462
//
sl@0
   463
	{
sl@0
   464
sl@0
   465
	TUint8 status=AtaRegister8(KAtaStatusRd8);
sl@0
   466
	if (status&KAtaStatusDrq)
sl@0
   467
		{
sl@0
   468
		__KTRACE_CARD_ERROR(KPBUSDRV,Kern::Printf("Ata:CheckForError-DRQ fail"));
sl@0
   469
		return KErrBadDrq;
sl@0
   470
		}
sl@0
   471
	if (status&KAtaStatusDwf)
sl@0
   472
		{
sl@0
   473
		__KTRACE_CARD_ERROR(KPBUSDRV,Kern::Printf("Ata:CheckForError-DWF fail"));
sl@0
   474
		return(KErrWrite);	
sl@0
   475
		}
sl@0
   476
	if (status&KAtaStatusErr)
sl@0
   477
		{
sl@0
   478
		__KTRACE_CARD_ERROR(KPBUSDRV,Kern::Printf("Ata:CheckForError-ERR fail"));
sl@0
   479
		return KErrAta;
sl@0
   480
		}
sl@0
   481
	return(KErrNone);
sl@0
   482
	}
sl@0
   483
sl@0
   484
TInt DPcCardMediaDriverAta::ProcessError(TInt anError)
sl@0
   485
//
sl@0
   486
// An error has occured - lets get more information
sl@0
   487
//
sl@0
   488
	{
sl@0
   489
sl@0
   490
	if (anError==KErrAta&&AtaRegister8(KAtaStatusRd8)&KAtaStatusErr)
sl@0
   491
		{
sl@0
   492
		TUint8 basic=AtaRegister8(KAtaErrorRd8);
sl@0
   493
#if (defined(__EPOC32__) && (defined(_DEBUG) || defined(SHOW_CARD_ERRORS)))
sl@0
   494
		TUint8 extended=0xFF;		// invalid
sl@0
   495
		SetAtaRegister8(KAtaCmdRequestSense,KAtaCommandWr8);	// Issue command - request sense
sl@0
   496
		Kern::NanoWait(400);					// Busy flag not asserted for 400ns
sl@0
   497
		WaitForNotBusy();
sl@0
   498
		if (!(AtaRegister8(KAtaStatusRd8)&KAtaStatusErr))
sl@0
   499
			extended=AtaRegister8(KAtaErrorRd8);
sl@0
   500
		__KTRACE_CARD_ERROR(KPBUSDRV,Kern::Printf("Ata:ProcessError-Basic:%xH Ext:%xH)",basic,extended));
sl@0
   501
#endif 
sl@0
   502
		if (basic&KAtaErrorUnc)
sl@0
   503
			return(KErrDied);
sl@0
   504
		else if (basic&(KAtaErrorBbk|KAtaErrorIdnf))
sl@0
   505
			return(KErrCorrupt);
sl@0
   506
		else if (basic&KAtaErrorAbort)
sl@0
   507
			return(KErrCancel);
sl@0
   508
		else
sl@0
   509
			return(KErrUnknown);
sl@0
   510
		}
sl@0
   511
	else
sl@0
   512
		return(anError);
sl@0
   513
	}
sl@0
   514
sl@0
   515
TInt DPcCardMediaDriverAta::EmptySectBufferToTrg(TUint8 *aSrc,TUint aTrgOffset,TInt aLen)
sl@0
   516
//
sl@0
   517
// Empty data from sector buffer (at specified offset within buffer) into
sl@0
   518
// destination descriptor.
sl@0
   519
//
sl@0
   520
	{
sl@0
   521
sl@0
   522
	TPtrC8 buf(aSrc,aLen);
sl@0
   523
	return iCurrentReq->WriteRemote(&buf,aTrgOffset);
sl@0
   524
	}
sl@0
   525
sl@0
   526
TInt DPcCardMediaDriverAta::LoadSectBufferFromSrc(TInt aLen, TUint8* aBuf)
sl@0
   527
//
sl@0
   528
// Load data from source descriptor into sector buffer
sl@0
   529
// Always called within exec. function.
sl@0
   530
//
sl@0
   531
	{
sl@0
   532
sl@0
   533
	TPtr8 buf(aBuf,aLen);
sl@0
   534
	TInt r=iCurrentReq->ReadRemote(&buf,iCmdInOffset);
sl@0
   535
	return r;
sl@0
   536
	}
sl@0
   537
sl@0
   538
TInt DPcCardMediaDriverAta::ReadSectorsCommand(TUint aFirstSector,TUint aBufOffset,TInt aLen)
sl@0
   539
//
sl@0
   540
// Start off a read of multiple sectors from the drive (command completed under interrupt/dfc).
sl@0
   541
//
sl@0
   542
	{
sl@0
   543
	__KTRACE_OPT(KPBUSDRV,Kern::Printf(">Ata:ReadSectors F:%x Off:%x L:%x",aFirstSector,aBufOffset,aLen));
sl@0
   544
sl@0
   545
	__ASSERT_DEBUG(aBufOffset<(TUint)KAtaSectorSize,Kern::PanicCurrentThread(_L("ReadSectorsCommand"),0));
sl@0
   546
	__ASSERT_DEBUG(aLen>0,Kern::PanicCurrentThread(_L("ReadSectorsCommand"),0));
sl@0
   547
sl@0
   548
	// Sector count - allow for not starting on sector boundary by adding buffer offset.  Allow for
sl@0
   549
	// not ending on sector boundary by adding sectorsize-1. Then divide by sector size.
sl@0
   550
	TInt tferSectorCount=(aLen+aBufOffset+KAtaSectorSizeMinusOne)>>KAtaSectorShift;
sl@0
   551
	iNextSector+=tferSectorCount;
sl@0
   552
	__ASSERT_DEBUG(tferSectorCount<=KMaxSectorsPerRead,Kern::PanicCurrentThread(_L("ReadSectorsCommand"),0));
sl@0
   553
sl@0
   554
	if (!iSocket->CardIsReady())
sl@0
   555
		return(KErrNotReady);
sl@0
   556
	AtaRegister8(KAtaStatusRd8);	// Clear any pending interrupt
sl@0
   557
	iSocket->InterruptEnable(EPccdIntIReq,0); // Enable card interrupt
sl@0
   558
	TInt err=IssueAtaCommand(KAtaCmdReadSectors,aFirstSector,tferSectorCount);
sl@0
   559
	if (err!=KErrNone)
sl@0
   560
		{
sl@0
   561
		iSocket->InterruptDisable(EPccdIntIReq); // Disable card interrupt
sl@0
   562
		iCardIreqDfc.Cancel();
sl@0
   563
		return err;
sl@0
   564
		}
sl@0
   565
	iCommandError=KErrNone;
sl@0
   566
	iNotBusyTickCount=KBusyTimeOut;
sl@0
   567
	iBusyTimeout.OneShot(NKern::TimerTicks(KNotBusyTestInterval));
sl@0
   568
	return(KErrNone);
sl@0
   569
	}
sl@0
   570
sl@0
   571
TInt DPcCardMediaDriverAta::InitiateWriteCommand(TUint aFirstSector,TInt aSectorCount,TUint8 *aSectBuffer)
sl@0
   572
//
sl@0
   573
// Start off an asynchronous write to the card. If successful, it leaves with a 
sl@0
   574
// timeout(ms timer) queued and card interrupts enabled.
sl@0
   575
//
sl@0
   576
	{
sl@0
   577
	__KTRACE_OPT(KPBUSDRV,Kern::Printf(">Ata:InitWrCmd F:%x C:%x",aFirstSector,aSectorCount));
sl@0
   578
sl@0
   579
	__ASSERT_DEBUG((aSectorCount>0 && aSectorCount<=KMaxSectorsPerWrite),Kern::PanicCurrentThread(_L("InitiateWriteCommand"),0));
sl@0
   580
sl@0
   581
	TInt err=IssueAtaCommand(KAtaCmdWriteSectors,aFirstSector,aSectorCount);
sl@0
   582
	if (err!=KErrNone)
sl@0
   583
		return(err);
sl@0
   584
	if (!iSocket->CardIsReady())
sl@0
   585
		return(KErrNotReady);
sl@0
   586
	if (!WaitForNotBusy())
sl@0
   587
		return(ProcessError(KErrTimedOut));
sl@0
   588
	AtaRegister8(KAtaStatusRd8);	// Clear any pending interrupt
sl@0
   589
	iSocket->InterruptEnable(EPccdIntIReq,0); // Enable card interrupt
sl@0
   590
	err=EmptySectBufferToDrive(aSectBuffer);
sl@0
   591
	if (err!=KErrNone)
sl@0
   592
		{
sl@0
   593
		iSocket->InterruptDisable(EPccdIntIReq); // Disable card interrupt
sl@0
   594
		iCardIreqDfc.Cancel();
sl@0
   595
		return(ProcessError(err));
sl@0
   596
		}
sl@0
   597
	iCommandError=KErrNone;
sl@0
   598
	iNotBusyTickCount=KBusyTimeOut;
sl@0
   599
	iBusyTimeout.OneShot(NKern::TimerTicks(KNotBusyTestInterval));
sl@0
   600
	iNextSector+=aSectorCount;
sl@0
   601
	return(KErrNone);
sl@0
   602
	}
sl@0
   603
sl@0
   604
TInt DPcCardMediaDriverAta::SectorBoundaryReadCheck(TUint aStartSector,TUint aStartSectOffset,Int64 anEndPos)
sl@0
   605
//
sl@0
   606
// Check for write request which doesn't lie entirely on a sector boundary and perform
sl@0
   607
// the appropriate sectors reads prior to writing if necessary
sl@0
   608
//
sl@0
   609
	{
sl@0
   610
sl@0
   611
	TInt err;
sl@0
   612
	TUint endSectOffset=((TUint)anEndPos&(~KAtaSectorMask));
sl@0
   613
	anEndPos-=1;
sl@0
   614
	anEndPos>>=KAtaSectorShift;
sl@0
   615
	TUint endSector=(TUint)anEndPos; // Sector number can't exceed 32bits
sl@0
   616
	TInt sectors=(endSector-aStartSector)+1;
sl@0
   617
	iLastSectorBufUsed=EFalse;
sl@0
   618
sl@0
   619
	if (aStartSectOffset||endSectOffset)
sl@0
   620
		{
sl@0
   621
		// If it requires a read of two consecutive sectors then read them in one go
sl@0
   622
		if (aStartSectOffset && endSectOffset && sectors==2)
sl@0
   623
			return(SectorRead(aStartSector,&iSectorBuf[0],2,KAtaCmdReadSectors));
sl@0
   624
		else 
sl@0
   625
			{
sl@0
   626
			// If write starts off a sector boundary or is a single sector write ending 
sl@0
   627
			// off a sector boundary then read first sector
sl@0
   628
			if (aStartSectOffset || (endSectOffset && sectors==1))
sl@0
   629
				{
sl@0
   630
				if ((err=SectorRead(aStartSector,&iSectorBuf[0]))!=KErrNone)
sl@0
   631
					return(err);
sl@0
   632
				}
sl@0
   633
			// If write doesn't end on a sector boundary then read the last sector
sl@0
   634
			if (endSectOffset && sectors>1)
sl@0
   635
				{
sl@0
   636
				TUint8* p=iSectorBuf;
sl@0
   637
				if (sectors<=KMaxSectorsPerWrite)
sl@0
   638
					p+=(sectors-1)<<KAtaSectorShift;
sl@0
   639
				else
sl@0
   640
					{
sl@0
   641
					p=iLastSectorBuf;
sl@0
   642
					iLastSectorBufUsed=ETrue;
sl@0
   643
					}
sl@0
   644
				return(SectorRead(endSector,p));
sl@0
   645
				}
sl@0
   646
			}
sl@0
   647
		}
sl@0
   648
	return(KErrNone);
sl@0
   649
	}
sl@0
   650
sl@0
   651
TInt DPcCardMediaDriverAta::SectorRead(TUint aFirstSector,TUint8 *aBuf,TInt aSectorCount,TUint8 aCmd)
sl@0
   652
//
sl@0
   653
// Read either 1 or 2 sectors into the sector buffer (synchronously)
sl@0
   654
//
sl@0
   655
	{
sl@0
   656
sl@0
   657
	TInt err;
sl@0
   658
	if ( (err=IssueAtaCommand(aCmd,aFirstSector,aSectorCount))==KErrNone)
sl@0
   659
		{
sl@0
   660
		if (
sl@0
   661
			(err=TransferSectBufferFromDrive(aBuf))!=KErrNone||
sl@0
   662
			(aSectorCount>1&&(err=TransferSectBufferFromDrive((TAny*)(aBuf+KAtaSectorSize)))!=KErrNone)||
sl@0
   663
			(err=FinishCommand())!=KErrNone
sl@0
   664
		   )
sl@0
   665
			err=ProcessError(err);
sl@0
   666
		}
sl@0
   667
	if (!iSocket->CardIsReady())
sl@0
   668
		err=KErrNotReady; // If media change - return not ready rather than anything else.
sl@0
   669
	return(err);
sl@0
   670
	}
sl@0
   671
sl@0
   672
void DPcCardMediaDriverAta::DumpIdentifyDriveInfo()
sl@0
   673
//
sl@0
   674
// Debug option to display the drive indentification info.
sl@0
   675
//
sl@0
   676
	{
sl@0
   677
#ifdef _DEBUG
sl@0
   678
	if (KDebugNum(KPBUSDRV))
sl@0
   679
		{
sl@0
   680
		for (TInt i=0;i<128;i+=8)
sl@0
   681
			{
sl@0
   682
			Kern::Printf("%02x%02x %02x%02x %02x%02x %02x%02x",iSectorBuf[i],iSectorBuf[i+1],iSectorBuf[i+2],iSectorBuf[i+3],iSectorBuf[i+4],\
sl@0
   683
						iSectorBuf[i+5],iSectorBuf[i+6],iSectorBuf[i+7]);
sl@0
   684
			}
sl@0
   685
		}
sl@0
   686
#endif 
sl@0
   687
	}
sl@0
   688
sl@0
   689
TInt DPcCardMediaDriverAta::IdentifyDrive()
sl@0
   690
//
sl@0
   691
// Get drive charateristics
sl@0
   692
//
sl@0
   693
	{
sl@0
   694
	__KTRACE_OPT(KPBUSDRV,Kern::Printf(">Ata:IdentifyDrive"));
sl@0
   695
sl@0
   696
	TInt err;
sl@0
   697
	if ((err=SectorRead(0,&iSectorBuf[0],1,KAtaCmdIdentifyDrive))!=KErrNone)
sl@0
   698
		return(err);
sl@0
   699
sl@0
   700
	DumpIdentifyDriveInfo();
sl@0
   701
	TBool lba=EFalse;
sl@0
   702
	Int64 s=0;
sl@0
   703
	if (*(TUint16*)(&iSectorBuf[KAtaIdCapabilities])&KAtaIdCapLbaSupported)
sl@0
   704
		{
sl@0
   705
		// Card indicates it supports LBA
sl@0
   706
		// Media size (in sectors) - 2 x halfwords @ KAtaIdTotalSectorsInLba.
sl@0
   707
		iDriveInfo.iTotalSectorsInLba=*(TInt*)(&iSectorBuf[KAtaIdTotalSectorsInLba]);
sl@0
   708
		s=iDriveInfo.iTotalSectorsInLba;
sl@0
   709
		s<<=KAtaSectorShift;
sl@0
   710
		if (s>0)
sl@0
   711
			lba=ETrue; // Epson PC card reports LBA supported but LBA size in bytes becomes zero
sl@0
   712
		} 
sl@0
   713
sl@0
   714
	iDriveInfo.iSupportsLba = lba;
sl@0
   715
	if (!lba)
sl@0
   716
		{
sl@0
   717
		// LBA not supported
sl@0
   718
		if (*(TUint16*)(&iSectorBuf[KAtaIdTranslationParams])&KAtaIdTrParamsValid)
sl@0
   719
			{
sl@0
   720
			// Current translation parameters are valid
sl@0
   721
			iDriveInfo.iCylinders=*(TUint16*)(&iSectorBuf[KAtaIdCurrentCylinders]);
sl@0
   722
			iDriveInfo.iHeads=*(TUint16*)(&iSectorBuf[KAtaIdCurrentHeads]);
sl@0
   723
			iDriveInfo.iSectorsPerTrack=*(TUint16*)(&iSectorBuf[KAtaIdCurrentSectorsPerTrack]);
sl@0
   724
			}
sl@0
   725
		else
sl@0
   726
			{ 
sl@0
   727
			// Use defaults
sl@0
   728
			iDriveInfo.iCylinders=*(TUint16*)(&iSectorBuf[KAtaIdDefaultCylinders]);
sl@0
   729
			iDriveInfo.iHeads=*(TUint16*)(&iSectorBuf[KAtaIdDefaultHeads]);
sl@0
   730
			iDriveInfo.iSectorsPerTrack=*(TUint16*)(&iSectorBuf[KAtaIdDefaultSectorsPerTrack]);
sl@0
   731
			} 
sl@0
   732
		iDriveInfo.iSectorsPerCylinder=(iDriveInfo.iHeads*iDriveInfo.iSectorsPerTrack);
sl@0
   733
		s=iDriveInfo.iCylinders;
sl@0
   734
		s*=iDriveInfo.iSectorsPerCylinder;
sl@0
   735
		s<<=KAtaSectorShift;
sl@0
   736
		if (iDriveInfo.iSectorsPerCylinder<=0||iDriveInfo.iSectorsPerTrack<=0)
sl@0
   737
			return(KErrCorrupt);
sl@0
   738
		}
sl@0
   739
sl@0
   740
	__KTRACE_OPT(KPBUSDRV,Kern::Printf("LBA      : %xH",iDriveInfo.iSupportsLba));
sl@0
   741
	__KTRACE_OPT(KPBUSDRV,Kern::Printf("Cylinders: %xH",iDriveInfo.iCylinders));
sl@0
   742
	__KTRACE_OPT(KPBUSDRV,Kern::Printf("Heads    : %xH",iDriveInfo.iHeads));
sl@0
   743
	__KTRACE_OPT(KPBUSDRV,Kern::Printf("Sectors  : %xH",iDriveInfo.iSectorsPerTrack));
sl@0
   744
	__KTRACE_OPT(KPBUSDRV,Kern::Printf("<Ata:IdentifyDrive (TS:%lxH)",s));
sl@0
   745
	SetTotalSizeInBytes(s);
sl@0
   746
	return(KErrNone);
sl@0
   747
	}
sl@0
   748
sl@0
   749
TInt DPcCardMediaDriverAta::ConfigAutoPowerDown()
sl@0
   750
//
sl@0
   751
// Set auto power down period to something sensible
sl@0
   752
//
sl@0
   753
	{
sl@0
   754
sl@0
   755
	TInt err;
sl@0
   756
	if ( (err=IssueAtaCommand(KAtaCmdIdle,0,200))==KErrNone) // 200x5mS=1S (aFirstSector doesn't matter).
sl@0
   757
		{
sl@0
   758
		if ((err=FinishCommand())!=KErrNone)
sl@0
   759
			err=ProcessError(err);
sl@0
   760
		}
sl@0
   761
	__KTRACE_OPT(KPBUSDRV,Kern::Printf("<Ata:ConfigAutoPowerDown-%d",err));
sl@0
   762
	return(err);
sl@0
   763
	}
sl@0
   764
sl@0
   765
TInt DPcCardMediaDriverAta::DoOpen()
sl@0
   766
//
sl@0
   767
// Open the media driver.
sl@0
   768
//
sl@0
   769
	{
sl@0
   770
sl@0
   771
	__KTRACE_OPT(KPBUSDRV,Kern::Printf(">Ata:DoOpen"));
sl@0
   772
	iCardIreqDfc.SetDfcQ(&iSocket->iDfcQ);
sl@0
   773
	iTimerDfc.SetDfcQ(&iSocket->iDfcQ);
sl@0
   774
sl@0
   775
	// Card ought to be ready but check we haven't had media change (this causes creation of card functions).
sl@0
   776
	TInt err=iSocket->CardIsReadyAndVerified();	// this may also fail with OOM or corrupt
sl@0
   777
	if (err!=KErrNone)
sl@0
   778
		return err;
sl@0
   779
sl@0
   780
	// Perform CIS validation - get back info. on card functions present. 
sl@0
   781
	TPccdType pt;
sl@0
   782
	if (iSocket->VerifyCard(pt)!=KErrNone)
sl@0
   783
		return(KErrUnknown);
sl@0
   784
sl@0
   785
	__KTRACE_OPT(KPBUSDRV,Kern::Printf("Ata:DoOpen-Check for ATA function, FuncCount=%d",pt.iFuncCount));
sl@0
   786
sl@0
   787
	// Check for ATA fixed disk function.
sl@0
   788
	TCisReader cisRd; 
sl@0
   789
	TInt f;
sl@0
   790
	TBool isAta=EFalse;
sl@0
   791
	for (f=0;f<pt.iFuncCount;f++)
sl@0
   792
		{
sl@0
   793
		if (pt.iFuncType[f]==EFixedDiskCard)
sl@0
   794
			{
sl@0
   795
			// Fixed disk function - check its an ATA. 
sl@0
   796
			TBuf8<KLargeTplBufSize> tpl;
sl@0
   797
			cisRd.SelectCis(iSocket->iSocketNumber,f);
sl@0
   798
			// Must start just after FuncId tuple.
sl@0
   799
			if (cisRd.FindReadTuple(KCisTplFuncId,tpl)!=KErrNone)
sl@0
   800
				continue;
sl@0
   801
			while (cisRd.FindReadTuple(KCisTplFunce,tpl)==KErrNone)
sl@0
   802
				{
sl@0
   803
				if (tpl[2]==0x01 && tpl[3]==0x01)	// Interface type - ATA
sl@0
   804
					isAta=ETrue;
sl@0
   805
				}
sl@0
   806
			if (isAta)
sl@0
   807
				break;
sl@0
   808
			}
sl@0
   809
		}
sl@0
   810
	if (!isAta)
sl@0
   811
		return(KErrUnknown);
sl@0
   812
	__KTRACE_OPT(KPBUSDRV,Kern::Printf("Ata:DoOpen-Is ATA"));
sl@0
   813
sl@0
   814
	// Determine best card configuration
sl@0
   815
	cisRd.Restart();
sl@0
   816
	TPcCardConfig cf;
sl@0
   817
	TInt opt=KInvalidConfOpt;
sl@0
   818
	while(cisRd.FindReadConfig(cf)==KErrNone)
sl@0
   819
		{
sl@0
   820
		if (
sl@0
   821
			 cf.IsMachineCompatible(iSocket->iSocketNumber,KPccdCompatNoVccCheck) && // Hitachi card has no 3.3V config entry
sl@0
   822
#if defined (SELECT_MEMORY_CONFIG)
sl@0
   823
			 (cf.iValidChunks==1 && __IS_COMMON_MEM(cf.iChnk[0].iMemType) && cf.iChnk[0].iMemLen==0x800)
sl@0
   824
#elif defined (SELECT_PRIMARY_IO_CONFIG)
sl@0
   825
			 (cf.iValidChunks==2 && __IS_IO_MEM(cf.iChnk[0].iMemType) && __IS_IO_MEM(cf.iChnk[1].iMemType) && cf.iChnk[0].iMemBaseAddr==0x1F0)
sl@0
   826
#else
sl@0
   827
			 // Choose 16 byte -  contiguous i/o option
sl@0
   828
			 (cf.iValidChunks==1 && __IS_IO_MEM(cf.iChnk[0].iMemType) && cf.iChnk[0].iMemLen==0x10)
sl@0
   829
#endif
sl@0
   830
		   ) 
sl@0
   831
			{
sl@0
   832
			opt=cf.iConfigOption;
sl@0
   833
			break;
sl@0
   834
			}
sl@0
   835
		}
sl@0
   836
	if (opt==KInvalidConfOpt)
sl@0
   837
		return(KErrNotSupported);
sl@0
   838
	__KTRACE_OPT(KPBUSDRV,Kern::Printf("Ata:DoOpen-ConfigOpt(%d)",opt));
sl@0
   839
	__KTRACE_OPT(KPBUSDRV,Kern::Printf("Ata:DoOpen-Pulsed Ints-%d",(cf.iInterruptInfo&KPccdIntPulse)));
sl@0
   840
sl@0
   841
	// Now configure the card. First configure it to memory mode. 
sl@0
   842
	cf.iConfigOption=0;
sl@0
   843
	err=iSocket->RequestConfig(f,this,cf,0);
sl@0
   844
	if (err!=KErrNone)
sl@0
   845
		return(err);
sl@0
   846
	if (cf.iRegPresent&KConfigAndStatusRegM)
sl@0
   847
		iSocket->WriteConfigReg(f,KConfigAndStatusReg,0); 
sl@0
   848
	if (cf.iRegPresent&KSocketAndCopyRegM)
sl@0
   849
		iSocket->WriteConfigReg(f,KSocketAndCopyReg,0);	// No twin cards
sl@0
   850
	iSocket->ReleaseConfig(f,this);
sl@0
   851
sl@0
   852
	cf.iConfigOption=(cf.iInterruptInfo&KPccdIntPulse)?opt:(opt|KConfOptLevIReqM);
sl@0
   853
//	cf.iConfigOption=(opt|KConfOptLevIReqM); // Force level mode interrupts
sl@0
   854
#if defined (FORCE_8BIT_ACCESSES)
sl@0
   855
#if defined (SELECT_MEMORY_CONFIG)
sl@0
   856
	cf.iChnk[0].iMemType=EPccdCommon8Mem;	// Force it to 8bit Common.
sl@0
   857
#else
sl@0
   858
	cf.iChnk[0].iMemType=EPccdIo8Mem;		// Force it to 8bit I/O.
sl@0
   859
#endif
sl@0
   860
#endif
sl@0
   861
sl@0
   862
	if ((err=iSocket->RequestConfig(f,this,cf,0))!=KErrNone)
sl@0
   863
		return(err);
sl@0
   864
sl@0
   865
	// Read back the config option register to verify it has been setup
sl@0
   866
	TUint8 v;
sl@0
   867
	if ((err=iSocket->ReadConfigReg(f,0,v))!=KErrNone||v!=(TUint8)cf.iConfigOption)
sl@0
   868
		return KErrBadPccdConfig;
sl@0
   869
	iCardFuncNum=f;
sl@0
   870
	__KTRACE_OPT(KPBUSDRV,Kern::Printf("Ata:DoOpen-Configured(%1xH) OK",v));
sl@0
   871
sl@0
   872
	TUint flag=(cf.iActiveSignals&KSigWaitRequired)?KPccdRequestWait:0;
sl@0
   873
	err=iDriveChunk.Create(iSocket,cf.iChnk[0],cf.iAccessSpeed,flag);
sl@0
   874
	if (err!=KErrNone)
sl@0
   875
		return(err);
sl@0
   876
	iDriveChunk.SetupChunkHw();
sl@0
   877
	iMemoryType=cf.iChnk[0].iMemType;
sl@0
   878
	__KTRACE_OPT(KPBUSDRV,Kern::Printf("Ata:DoOpen-Requested Mem OK"));
sl@0
   879
sl@0
   880
	iSocket->InterruptDisable(EPccdIntIReq);
sl@0
   881
	iCardIntCallBack.iSocket=iSocket;
sl@0
   882
	iCardIntCallBack.Add();
sl@0
   883
	SetAtaRegister8(0,KAtaDeviceCtlWr8);	// Enable interrupts
sl@0
   884
sl@0
   885
	SetCurrentConsumption(KIdleCurrentInMilliAmps);
sl@0
   886
	__KTRACE_OPT(KPBUSDRV,Kern::Printf("<Ata:DoOpen-OK"));
sl@0
   887
	return(KErrNone);
sl@0
   888
	}
sl@0
   889
sl@0
   890
TBool DPcCardMediaDriverAta::CardPoweredDown()
sl@0
   891
//
sl@0
   892
// Returns EFalse as long as card hasn't received power down (emergency or normal).
sl@0
   893
//
sl@0
   894
	{
sl@0
   895
sl@0
   896
	// Emergency power down may result in card being powered down before PC Card
sl@0
   897
	// Controller status is updated - check for EPD as well as PC Card Contoller.
sl@0
   898
	return(!Kern::PowerGood() || !iSocket->CardIsReady());
sl@0
   899
	}
sl@0
   900
sl@0
   901
void DPcCardMediaDriverAta::IncrementSectBufPtr()
sl@0
   902
//
sl@0
   903
//
sl@0
   904
//
sl@0
   905
	{
sl@0
   906
sl@0
   907
	iSectBufPtr+=KAtaSectorSize;
sl@0
   908
	if ((iSectBufPtr-&iSectorBuf[0])>=KSectBufSizeInBytes)
sl@0
   909
		iSectBufPtr=&iSectorBuf[0];
sl@0
   910
	}
sl@0
   911
sl@0
   912
TInt DPcCardMediaDriverAta::Request(TLocDrvRequest& m)
sl@0
   913
	{
sl@0
   914
	__KTRACE_OPT(KLOCDRV,Kern::Printf("Ata:Req %08x id %d",&m,m.Id()));
sl@0
   915
	TInt r=KErrNotSupported;
sl@0
   916
	TInt id=m.Id();
sl@0
   917
	if (id==DLocalDrive::ECaps)
sl@0
   918
		{
sl@0
   919
		TLocalDriveCapsV6& c=*(TLocalDriveCapsV6*)m.RemoteDes();
sl@0
   920
		r=Caps(c);
sl@0
   921
		c.iSize=m.Drive()->iPartitionLen;
sl@0
   922
		c.iPartitionType=m.Drive()->iPartitionType;
sl@0
   923
		return r;
sl@0
   924
		}
sl@0
   925
	if (iCurrentReq)
sl@0
   926
		{
sl@0
   927
		// a request is already in progress, so hold on to this one
sl@0
   928
		__KTRACE_OPT(KLOCDRV,Kern::Printf("Ata:Req %08x ret 1",&m));
sl@0
   929
		return KMediaDriverDeferRequest;
sl@0
   930
		}
sl@0
   931
	iCurrentReq=&m;
sl@0
   932
	switch (id)
sl@0
   933
		{
sl@0
   934
		case DLocalDrive::ERead:
sl@0
   935
			r=DoRead();
sl@0
   936
			break;
sl@0
   937
		case DLocalDrive::EWrite:
sl@0
   938
			r=DoWrite();
sl@0
   939
			break;
sl@0
   940
		case DLocalDrive::EFormat:
sl@0
   941
			r=DoFormat();
sl@0
   942
			break;
sl@0
   943
		case DLocalDrive::EEnlarge:
sl@0
   944
		case DLocalDrive::EReduce:
sl@0
   945
		default:
sl@0
   946
			r=KErrNotSupported;
sl@0
   947
			break;
sl@0
   948
		}
sl@0
   949
	__KTRACE_OPT(KLOCDRV,Kern::Printf("Ata:Req %08x cmp %d",&m,r));
sl@0
   950
	if (r!=KErrNone)
sl@0
   951
		iCurrentReq=NULL;
sl@0
   952
	return r;
sl@0
   953
	}
sl@0
   954
sl@0
   955
void DPcCardMediaDriverAta::NotifyPowerDown()
sl@0
   956
	{
sl@0
   957
	__KTRACE_OPT(KPBUSDRV,Kern::Printf(">Ata:NotifyPowerDown"));
sl@0
   958
	Complete(KErrNotReady);
sl@0
   959
	Reset();
sl@0
   960
	}
sl@0
   961
sl@0
   962
void DPcCardMediaDriverAta::NotifyEmergencyPowerDown()
sl@0
   963
	{
sl@0
   964
	__KTRACE_OPT(KPBUSDRV,Kern::Printf(">Ata:NotifyEmergencyPowerDown"));
sl@0
   965
	TInt r=KErrNotReady;
sl@0
   966
	if (iCritical)
sl@0
   967
		r=KErrAbort;
sl@0
   968
	EndInCritical();
sl@0
   969
	Complete(r);
sl@0
   970
	Reset();
sl@0
   971
	}
sl@0
   972
sl@0
   973
void DPcCardMediaDriverAta::TimerDfcFunction(TAny* aPtr)
sl@0
   974
//
sl@0
   975
// DFC callback from not-busy timer
sl@0
   976
//
sl@0
   977
	{
sl@0
   978
	DPcCardMediaDriverAta &md=*(DPcCardMediaDriverAta*)aPtr;
sl@0
   979
	__KTRACE_OPT2(KPBUSDRV,KFAIL,Kern::Printf(">Ata:TimerDfcFunction TC:%d",md.iNotBusyTickCount));
sl@0
   980
	TInt r=1;
sl@0
   981
	if (!md.CardPoweredDown())
sl@0
   982
		{
sl@0
   983
		md.iDriveChunk.SetupChunkHw();
sl@0
   984
		TUint8 status=md.AtaRegister8(KAtaStatusRd8); // Clears interrupt
sl@0
   985
		if (!(status&KAtaStatusBusy))
sl@0
   986
			{
sl@0
   987
			// It is not-busy so process it as we would from an interrupt
sl@0
   988
			__KTRACE_OPT2(KPBUSDRV,KFAIL,Kern::Printf("Card not busy"));
sl@0
   989
			r=KErrNone;
sl@0
   990
#ifdef COUNT_TIMEOUTS
sl@0
   991
			++md.iTimeouts;
sl@0
   992
			md.iNewTimeOut=ETrue;
sl@0
   993
			if (md.iIndex<=6)
sl@0
   994
				{
sl@0
   995
				md.iInfo[md.iIndex++]=md.iCmdInOffset;
sl@0
   996
				md.iInfo[md.iIndex++]=md.iCmdEndOffset;
sl@0
   997
				}
sl@0
   998
#endif
sl@0
   999
			}
sl@0
  1000
		else
sl@0
  1001
			{
sl@0
  1002
			// still busy so count tick and restart timer
sl@0
  1003
			if (--md.iNotBusyTickCount==0)
sl@0
  1004
				{
sl@0
  1005
				__KTRACE_OPT2(KPBUSDRV,KFAIL,Kern::Printf("Timed out"));
sl@0
  1006
				r=KErrTimedOut;		// time out the request
sl@0
  1007
				}
sl@0
  1008
			else
sl@0
  1009
				{
sl@0
  1010
				__KTRACE_OPT2(KPBUSDRV,KFAIL,Kern::Printf("Restart timer"));
sl@0
  1011
				md.iBusyTimeout.OneShot(NKern::TimerTicks(KNotBusyTestInterval));
sl@0
  1012
				}
sl@0
  1013
			}
sl@0
  1014
		}
sl@0
  1015
	else
sl@0
  1016
		r=KErrNotReady;
sl@0
  1017
	__KTRACE_OPT2(KPBUSDRV,KFAIL,Kern::Printf("<Ata:TimerDfcFunction r=%d",r));
sl@0
  1018
	if (r<=0)
sl@0
  1019
		{
sl@0
  1020
		// card is not-busy, powered down or timed out
sl@0
  1021
		md.iSocket->InterruptDisable(EPccdIntIReq); // Disable IREQ in controller
sl@0
  1022
		md.iCardIreqDfc.Cancel();	// so we don't run this twice
sl@0
  1023
		md.iCommandError=r;
sl@0
  1024
		CardIreqDfcFunction(&md);
sl@0
  1025
		}
sl@0
  1026
	}
sl@0
  1027
sl@0
  1028
void DPcCardMediaDriverAta::CardIntCallBack(TAny* aMediaDriver, TInt)
sl@0
  1029
//
sl@0
  1030
// Card Interrupt callback
sl@0
  1031
//
sl@0
  1032
	{
sl@0
  1033
	__TRACE_TIMING(0x104);
sl@0
  1034
	DPcCardMediaDriverAta &md=*(DPcCardMediaDriverAta*)aMediaDriver;
sl@0
  1035
	md.iSocket->InterruptDisable(EPccdIntIReq); // Disable IREQ in controller
sl@0
  1036
	md.iCardIreqDfc.Add();
sl@0
  1037
#ifdef COUNT_TIMEOUTS
sl@0
  1038
	++md.iInts;
sl@0
  1039
#endif
sl@0
  1040
	}
sl@0
  1041
sl@0
  1042
void DPcCardMediaDriverAta::CardIreqDfcFunction(TAny* aPtr)
sl@0
  1043
	{
sl@0
  1044
sl@0
  1045
	DPcCardMediaDriverAta &md=*(DPcCardMediaDriverAta*)aPtr;
sl@0
  1046
	TInt err=md.iCommandError;
sl@0
  1047
	TBool queueDfc=md.CardPoweredDown();
sl@0
  1048
	if (queueDfc)
sl@0
  1049
		err=KErrNotReady;
sl@0
  1050
	else if (err!=KErrNone)
sl@0
  1051
		queueDfc=ETrue;		// timed out
sl@0
  1052
	else
sl@0
  1053
		{
sl@0
  1054
		md.iDriveChunk.SetupChunkHw();
sl@0
  1055
		TUint8 status=md.AtaRegister8(KAtaStatusRd8); // Clears interrupt
sl@0
  1056
		if (!(status&KAtaStatusBusy))
sl@0
  1057
			queueDfc=md.DoCardNotBusy(err);
sl@0
  1058
		}
sl@0
  1059
	TBool cmd_done=EFalse;
sl@0
  1060
	if (queueDfc)
sl@0
  1061
		{
sl@0
  1062
		md.iCommandError=err;
sl@0
  1063
		cmd_done=md.CmdDfc();
sl@0
  1064
		}
sl@0
  1065
	if (!queueDfc)
sl@0
  1066
		{
sl@0
  1067
		// command still executing so reenable interrupts
sl@0
  1068
		md.iSocket->InterruptEnable(EPccdIntIReq,0);
sl@0
  1069
		}
sl@0
  1070
	if (!cmd_done)
sl@0
  1071
		{
sl@0
  1072
		// quickly check if card is already not busy
sl@0
  1073
		// this handles cards which return data very quickly
sl@0
  1074
		md.iDriveChunk.SetupChunkHw();
sl@0
  1075
		TUint8 status=md.AtaRegister8(KAtaStatusRd8); // Clears interrupt
sl@0
  1076
		if (!(status&KAtaStatusBusy))
sl@0
  1077
			{
sl@0
  1078
			md.iSocket->InterruptDisable(EPccdIntIReq);
sl@0
  1079
			md.iCardIreqDfc.Enque();
sl@0
  1080
#ifdef COUNT_TIMEOUTS
sl@0
  1081
			++md.iImmediateNotBusy;
sl@0
  1082
#endif
sl@0
  1083
			}
sl@0
  1084
		else
sl@0
  1085
			{
sl@0
  1086
			md.iBusyTimeout.Cancel();
sl@0
  1087
			md.iTimerDfc.Cancel();
sl@0
  1088
			md.iBusyTimeout.OneShot(NKern::TimerTicks(KNotBusyTestInterval));
sl@0
  1089
			}
sl@0
  1090
		}
sl@0
  1091
	}
sl@0
  1092
sl@0
  1093
TBool DPcCardMediaDriverAta::DoCardNotBusy(TInt &anErr)
sl@0
  1094
//
sl@0
  1095
// Card not busy interrupt - return ETrue when need to queue dfc
sl@0
  1096
//
sl@0
  1097
	{
sl@0
  1098
sl@0
  1099
	anErr=KErrNone;
sl@0
  1100
	if (iCardStatus==ECardWrite || iCardStatus==ECardFormat)
sl@0
  1101
		{
sl@0
  1102
		// For write/format commands we only update the out-pointer when the card becomes
sl@0
  1103
		// not-busy following the point we transfered the block of data to the card.
sl@0
  1104
		iCmdOutOffset+=(KAtaSectorSize-iSectBufOffset);
sl@0
  1105
		iSectBufOffset=0;
sl@0
  1106
		if (iCmdOutOffset<iCmdEndOffset)
sl@0
  1107
			{
sl@0
  1108
			TUint8* pB=iSectBufPtr;
sl@0
  1109
			if (iLastSectorBufUsed && iCmdLength-iCmdOutOffset<=(TUint)KAtaSectorSize)
sl@0
  1110
				pB=iLastSectorBuf;	// use different buffer for last sector of unaligned write
sl@0
  1111
			anErr=EmptySectBufferToDrive(pB);
sl@0
  1112
			if (anErr!=KErrNone)
sl@0
  1113
				return(ETrue);
sl@0
  1114
			if (iCardStatus==ECardWrite)
sl@0
  1115
				iSectBufPtr+=KAtaSectorSize;
sl@0
  1116
			}
sl@0
  1117
		else
sl@0
  1118
			{
sl@0
  1119
			anErr=CheckForError();
sl@0
  1120
			return(ETrue);
sl@0
  1121
			}
sl@0
  1122
		}
sl@0
  1123
	if (iCardStatus==ECardRead)
sl@0
  1124
		{
sl@0
  1125
		// For read commands we only update the in-pointer here. The out-pointer is
sl@0
  1126
		// updated by the DFC as data is written to target thread
sl@0
  1127
sl@0
  1128
		// Before we read the data from the card, perform the in-pointer incremeting now. 
sl@0
  1129
		// If we are about to queue a DFC then let the DFC read from the card. Otherwise,
sl@0
  1130
		// reading from the card may result in the next sector of data being available
sl@0
  1131
		// before we're ready for it.
sl@0
  1132
sl@0
  1133
		// If first interrupt after command initiated then allow for sector buffer offset
sl@0
  1134
		TInt toEOBuf=(iCmdInOffset==0)?(KAtaSectorSize-iSectBufOffset):KAtaSectorSize;
sl@0
  1135
		TInt remaining=(TInt)(iCmdEndOffset-iCmdInOffset);
sl@0
  1136
		iCmdInOffset+=Min(remaining,toEOBuf);
sl@0
  1137
		if ((iSectBufPtr-&iSectorBuf[0])>=KSectBufSizeInBytesMinusOneSector || iCmdInOffset>=iCmdEndOffset)
sl@0
  1138
			return(ETrue); // Queue a DFC
sl@0
  1139
		else
sl@0
  1140
			{
sl@0
  1141
			anErr=LoadSectBufferFromDrive(iSectBufPtr);
sl@0
  1142
			if (anErr!=KErrNone)
sl@0
  1143
				return(ETrue);
sl@0
  1144
			IncrementSectBufPtr();
sl@0
  1145
			}
sl@0
  1146
		}
sl@0
  1147
	return(EFalse);
sl@0
  1148
	}
sl@0
  1149
sl@0
  1150
void DPcCardMediaDriverAta::SyncBusyTimerCallBack(TAny* aBusyFlag)
sl@0
  1151
//
sl@0
  1152
// Wait for not busy timeout callback
sl@0
  1153
//
sl@0
  1154
	{
sl@0
  1155
sl@0
  1156
	*(TBool*)aBusyFlag=ETrue;
sl@0
  1157
	}
sl@0
  1158
sl@0
  1159
void DPcCardMediaDriverAta::AsyncBusyTimerCallBack(TAny* aMediaDriver)
sl@0
  1160
//
sl@0
  1161
// Wait for not busy timeout callback
sl@0
  1162
//
sl@0
  1163
	{
sl@0
  1164
sl@0
  1165
	__KTRACE_OPT(KFAIL,Kern::Printf("!,"));
sl@0
  1166
	DPcCardMediaDriverAta &md=*(DPcCardMediaDriverAta*)aMediaDriver;
sl@0
  1167
	md.iTimerDfc.Add();
sl@0
  1168
	}
sl@0
  1169
sl@0
  1170
TBool DPcCardMediaDriverAta::CmdDfc()
sl@0
  1171
//
sl@0
  1172
// Dfc to complete an asynchronous command
sl@0
  1173
//
sl@0
  1174
	{
sl@0
  1175
sl@0
  1176
	TInt err;
sl@0
  1177
sl@0
  1178
	__KTRACE_OPT(KPBUSDRV,Kern::Printf(">Ata:CmdDfc status %d in %x out %x len %x",iCardStatus,iCmdInOffset,iCmdOutOffset,iCmdLength));
sl@0
  1179
sl@0
  1180
	iBusyTimeout.Cancel();
sl@0
  1181
	iTimerDfc.Cancel();
sl@0
  1182
	if (DoCmdDfc(err))	// this requeues timer and reenables interrupts if command still executing
sl@0
  1183
		{
sl@0
  1184
		// Command has been completed for one reason or other
sl@0
  1185
		EndInCritical();
sl@0
  1186
		if (err!=KErrNone)
sl@0
  1187
			err=ProcessError(err);
sl@0
  1188
sl@0
  1189
		// If emergency power down on write/format - return abort rather than anything else.
sl@0
  1190
		if (!Kern::PowerGood() && iCardStatus!=ECardRead)
sl@0
  1191
			err=KErrAbort;
sl@0
  1192
		// If media change - return not ready rather than anything else.
sl@0
  1193
		else if (!iSocket->CardIsReady())
sl@0
  1194
			err=KErrNotReady;
sl@0
  1195
		__KTRACE_OPT(KFAIL,Kern::Printf("a%d",err));
sl@0
  1196
		if (err==KErrNone)
sl@0
  1197
			{
sl@0
  1198
			// may need to issue another command here
sl@0
  1199
			if (iCmdOutOffset<iCmdLength)
sl@0
  1200
				{
sl@0
  1201
				if (iCardStatus==ECardRead)
sl@0
  1202
					{
sl@0
  1203
					__KTRACE_OPT(KFAIL,Kern::Printf("+R"));
sl@0
  1204
					__KTRACE_OPT(KPBUSDRV,Kern::Printf(">Ata:NewReadCmd"));
sl@0
  1205
					iSectBufOffset=0;
sl@0
  1206
#ifdef COUNT_TIMEOUTS
sl@0
  1207
					++iChainedReads;
sl@0
  1208
#endif
sl@0
  1209
					err=InitiateAsyncRead();
sl@0
  1210
					if (err==KErrNone)
sl@0
  1211
						return ETrue;
sl@0
  1212
					}
sl@0
  1213
				else
sl@0
  1214
					{
sl@0
  1215
					__KTRACE_OPT(KFAIL,Kern::Printf("+W"));
sl@0
  1216
					__KTRACE_OPT(KPBUSDRV,Kern::Printf(">Ata:NewWriteCmd"));
sl@0
  1217
#ifdef COUNT_TIMEOUTS
sl@0
  1218
					++iChainedWrites;
sl@0
  1219
#endif
sl@0
  1220
					err=InitiateAsyncWrite();
sl@0
  1221
					if (err==KErrNone)
sl@0
  1222
						return ETrue;
sl@0
  1223
					}
sl@0
  1224
				}
sl@0
  1225
			}
sl@0
  1226
		iCardStatus=ECardIdle;		// Command now complete
sl@0
  1227
		SetCurrentConsumption(KIdleCurrentInMilliAmps);
sl@0
  1228
sl@0
  1229
#if (defined(_DEBUG) || defined(SHOW_CARD_ERRORS))
sl@0
  1230
		if (err!=KErrNone&&err!=KErrTooBig)
sl@0
  1231
			{
sl@0
  1232
			__KTRACE_CARD_ERROR(KPBUSDRV,Kern::Printf("<DFC(L:%d P:%xH)-%d",iDbgLen,iDbgPos,err));
sl@0
  1233
			iDbgLastError=err;
sl@0
  1234
			}
sl@0
  1235
#endif
sl@0
  1236
		__TRACE_TIMING(0x109);
sl@0
  1237
		Complete(err);
sl@0
  1238
		return ETrue;
sl@0
  1239
		}
sl@0
  1240
	return EFalse;
sl@0
  1241
	}
sl@0
  1242
sl@0
  1243
TBool DPcCardMediaDriverAta::DoCmdDfc(TInt &anErr)
sl@0
  1244
//
sl@0
  1245
// Return ETrue when complete
sl@0
  1246
//
sl@0
  1247
	{
sl@0
  1248
sl@0
  1249
	if (CardPoweredDown())
sl@0
  1250
		{
sl@0
  1251
		anErr=KErrNotReady;
sl@0
  1252
		return(ETrue);
sl@0
  1253
		}
sl@0
  1254
	anErr=iCommandError;
sl@0
  1255
	if (iCommandError!=KErrNone)
sl@0
  1256
		return(ETrue);
sl@0
  1257
sl@0
  1258
	if (iCardStatus==ECardWrite||iCardStatus==ECardFormat)
sl@0
  1259
		return(ETrue);
sl@0
  1260
	else
sl@0
  1261
		{
sl@0
  1262
		// Read command, we postponed loading the last sector
sl@0
  1263
		__TRACE_TIMING(0x105);
sl@0
  1264
		if ((anErr=LoadSectBufferFromDrive(iSectBufPtr))!=KErrNone)
sl@0
  1265
			return(ETrue);
sl@0
  1266
sl@0
  1267
		// In case command still executing, queue another timeout and re-enable interrupts
sl@0
  1268
		iSocket->InterruptEnable(EPccdIntIReq,0);
sl@0
  1269
		iNotBusyTickCount=KBusyTimeOut;
sl@0
  1270
		iBusyTimeout.OneShot(NKern::TimerTicks(KNotBusyTestInterval));
sl@0
  1271
sl@0
  1272
		__TRACE_TIMING(0x106);
sl@0
  1273
		IncrementSectBufPtr();
sl@0
  1274
		if ((anErr=EmptySectBufferToTrg(&iSectorBuf[0]+iSectBufOffset,iCmdOutOffset,iCmdInOffset-iCmdOutOffset))!=KErrNone)
sl@0
  1275
			{
sl@0
  1276
			iSocket->InterruptDisable(EPccdIntIReq); // Disable IREQ in controller
sl@0
  1277
			iBusyTimeout.Cancel();
sl@0
  1278
			iTimerDfc.Cancel();
sl@0
  1279
			iCardIreqDfc.Cancel();
sl@0
  1280
			return(ETrue);
sl@0
  1281
			}
sl@0
  1282
		__TRACE_TIMING(0x107);
sl@0
  1283
		iSectBufOffset=0;		// From now on we always start on sector boundary
sl@0
  1284
		iCmdOutOffset=iCmdInOffset;
sl@0
  1285
		if (iCmdOutOffset<iCmdEndOffset)
sl@0
  1286
			return(EFalse);
sl@0
  1287
		iSocket->InterruptDisable(EPccdIntIReq); // Disable IREQ in controller
sl@0
  1288
		iBusyTimeout.Cancel();
sl@0
  1289
		iTimerDfc.Cancel();
sl@0
  1290
		iCardIreqDfc.Cancel();
sl@0
  1291
		anErr=FinishCommand();	// This functions involves polling for not busy
sl@0
  1292
		return(ETrue);
sl@0
  1293
		}
sl@0
  1294
	__TRACE_TIMING(0x108);
sl@0
  1295
	}
sl@0
  1296
sl@0
  1297
DPhysicalDeviceMediaAta::DPhysicalDeviceMediaAta()
sl@0
  1298
//
sl@0
  1299
// Constructor
sl@0
  1300
//
sl@0
  1301
	{
sl@0
  1302
	iUnitsMask=0x1;
sl@0
  1303
	iVersion=TVersion(KMediaDriverInterfaceMajorVersion,KMediaDriverInterfaceMinorVersion,KMediaDriverInterfaceBuildVersion);
sl@0
  1304
	}
sl@0
  1305
sl@0
  1306
TInt DPhysicalDeviceMediaAta::Install()
sl@0
  1307
//
sl@0
  1308
// Install the PC Card ATA Media PDD.
sl@0
  1309
//
sl@0
  1310
	{
sl@0
  1311
	return SetName(&KPddName);
sl@0
  1312
	}
sl@0
  1313
sl@0
  1314
void DPhysicalDeviceMediaAta::GetCaps(TDes8 &/* aDes */) const
sl@0
  1315
//
sl@0
  1316
// Return the media drivers capabilities.
sl@0
  1317
//
sl@0
  1318
	{
sl@0
  1319
	}
sl@0
  1320
								 
sl@0
  1321
TInt DPhysicalDeviceMediaAta::Create(DBase*& aChannel, TInt aMediaId, const TDesC8* /*anInfo*/, const TVersion& aVer)
sl@0
  1322
//
sl@0
  1323
// Create a PC Card ATA media driver.
sl@0
  1324
//
sl@0
  1325
	{
sl@0
  1326
	if (!Kern::QueryVersionSupported(iVersion,aVer))
sl@0
  1327
		return KErrNotSupported;
sl@0
  1328
	DPcCardMediaDriverAta* pD=new DPcCardMediaDriverAta(aMediaId);
sl@0
  1329
	aChannel=pD;
sl@0
  1330
	TInt r=KErrNoMemory;
sl@0
  1331
	if (pD)
sl@0
  1332
		r=pD->Open();
sl@0
  1333
	if (r==KErrNone)
sl@0
  1334
		pD->OpenMediaDriverComplete(KErrNone);
sl@0
  1335
	return r;
sl@0
  1336
	}
sl@0
  1337
sl@0
  1338
TInt DPhysicalDeviceMediaAta::Validate(TInt aDeviceType, const TDesC8* anInfo, const TVersion& aVer)
sl@0
  1339
	{
sl@0
  1340
	if (!Kern::QueryVersionSupported(iVersion,aVer))
sl@0
  1341
		return KErrNotSupported;
sl@0
  1342
	if (aDeviceType!=MEDIA_DEVICE_PCCARD)
sl@0
  1343
		return KErrNotSupported;
sl@0
  1344
	return KErrNone;
sl@0
  1345
	}
sl@0
  1346
sl@0
  1347
TInt DPhysicalDeviceMediaAta::Info(TInt aFunction, TAny*)
sl@0
  1348
//
sl@0
  1349
// Return the priority of this media driver
sl@0
  1350
//
sl@0
  1351
	{
sl@0
  1352
	if (aFunction==EPriority)
sl@0
  1353
		return KAtaDriverPriority;
sl@0
  1354
	return KErrNotSupported;
sl@0
  1355
	}
sl@0
  1356
sl@0
  1357
DPcCardMediaDriverAta::DPcCardMediaDriverAta(TInt aMediaId)
sl@0
  1358
//
sl@0
  1359
// Constructor.
sl@0
  1360
//
sl@0
  1361
	:	DMediaDriver(aMediaId),
sl@0
  1362
		iCardIntCallBack(CardIntCallBack,this,KPccdIntMaskIReq),
sl@0
  1363
		iBusyTimeout(AsyncBusyTimerCallBack,this),
sl@0
  1364
		iCardIreqDfc(CardIreqDfcFunction,this,2),
sl@0
  1365
		iTimerDfc(TimerDfcFunction,this,2)
sl@0
  1366
	{
sl@0
  1367
sl@0
  1368
	iMemoryType=EPccdIo8Mem;
sl@0
  1369
//	iCommandError=KErrNone;
sl@0
  1370
//	TUint iCmdInOffset=0;
sl@0
  1371
//	TUint iCmdOutOffset=0;
sl@0
  1372
//	iCmdEndOffset=0;
sl@0
  1373
//	iSectBufPtr=NULL;
sl@0
  1374
//	iSectBufOffset=0;
sl@0
  1375
	iCardStatus=ECardIdle;
sl@0
  1376
//	iHiddenSectors=0;
sl@0
  1377
	iCardFuncNum=-1;
sl@0
  1378
	}
sl@0
  1379
sl@0
  1380
TInt DPcCardMediaDriverAta::Open()
sl@0
  1381
//
sl@0
  1382
// Open the media driver.
sl@0
  1383
//
sl@0
  1384
	{
sl@0
  1385
sl@0
  1386
	// Open the driver and get drive characteristics
sl@0
  1387
	iSocket=((DPcCardSocket*)((DPBusPrimaryMedia*)iPrimaryMedia)->iSocket);
sl@0
  1388
	__KTRACE_OPT(KPBUSDRV,Kern::Printf(">Ata:Open on socket %d",iSocket->iSocketNumber));
sl@0
  1389
	TInt r=DoOpen();
sl@0
  1390
	if (r==KErrNone)
sl@0
  1391
		r=IdentifyDrive();
sl@0
  1392
	if (r!=KErrNone)
sl@0
  1393
		{
sl@0
  1394
		DoClose();
sl@0
  1395
		if (!iSocket->CardIsReady())
sl@0
  1396
			r=KErrNotReady; // If media change - return not ready rather than anything else.
sl@0
  1397
		}
sl@0
  1398
	__KTRACE_OPT(KPBUSDRV,Kern::Printf("<Ata:Open-%d",r));
sl@0
  1399
	return r;
sl@0
  1400
	}
sl@0
  1401
sl@0
  1402
TInt DPcCardMediaDriverAta::CheckDevice(TBool aCheckPower)
sl@0
  1403
//
sl@0
  1404
// Check the device before initiating a command
sl@0
  1405
//
sl@0
  1406
	{
sl@0
  1407
	
sl@0
  1408
	if (iSocket->CardIsReadyAndVerified()!=KErrNone)
sl@0
  1409
		return KErrNotReady;
sl@0
  1410
	if (aCheckPower && Kern::MachinePowerStatus()<ELow)
sl@0
  1411
		return KErrBadPower;
sl@0
  1412
	return KErrNone;
sl@0
  1413
	}
sl@0
  1414
sl@0
  1415
TInt DPcCardMediaDriverAta::DoRead()
sl@0
  1416
//
sl@0
  1417
// Read from specified area of media.
sl@0
  1418
//
sl@0
  1419
	{
sl@0
  1420
sl@0
  1421
	Int64 aPos=iCurrentReq->Pos();
sl@0
  1422
	TInt aLength=(TInt)iCurrentReq->Length();
sl@0
  1423
	TInt err;
sl@0
  1424
	iCmdOutOffset=0;	// Progress monitor - data delivered to target
sl@0
  1425
#if (defined(_DEBUG) || defined(SHOW_CARD_ERRORS))
sl@0
  1426
	iDbgPos=(TUint)aPos;
sl@0
  1427
	iDbgLen=aLength;
sl@0
  1428
#endif
sl@0
  1429
	err=CheckDevice(EFalse);
sl@0
  1430
	if (err==KErrNone)
sl@0
  1431
		{
sl@0
  1432
		iDriveChunk.SetupChunkHw(); // Enable our h/w chunk
sl@0
  1433
	
sl@0
  1434
		TUint sectorBufOffset=(TUint)aPos&(~KAtaSectorMask);
sl@0
  1435
		Int64 firstSector=(aPos>>KAtaSectorShift);
sl@0
  1436
		iCmdLength=aLength;
sl@0
  1437
sl@0
  1438
		SetCurrentConsumption(KReadCurrentInMilliAmps);
sl@0
  1439
sl@0
  1440
		// Start an asynchronous read
sl@0
  1441
		iCmdInOffset=0; 					// Data received from card
sl@0
  1442
		iNextSector=(TUint)firstSector;
sl@0
  1443
		iSectBufOffset=sectorBufOffset;
sl@0
  1444
		err=InitiateAsyncRead();
sl@0
  1445
		if (err==KErrNone)
sl@0
  1446
			return KErrNone;
sl@0
  1447
sl@0
  1448
		iCardStatus=ECardIdle;
sl@0
  1449
		SetCurrentConsumption(KIdleCurrentInMilliAmps);
sl@0
  1450
		if (!iSocket->CardIsReady())
sl@0
  1451
			err=KErrNotReady; // If media change - return not ready rather than anything else.
sl@0
  1452
		}
sl@0
  1453
sl@0
  1454
#if (defined(_DEBUG) || defined(SHOW_CARD_ERRORS))
sl@0
  1455
	__KTRACE_CARD_ERROR(KPBUSDRV,Kern::Printf("<Ata:Read(L:%d P:%xH)-%d",iDbgLen,iDbgPos,err));
sl@0
  1456
	iDbgLastError=err;
sl@0
  1457
#endif
sl@0
  1458
	return err;
sl@0
  1459
	}
sl@0
  1460
sl@0
  1461
TInt DPcCardMediaDriverAta::InitiateAsyncRead()
sl@0
  1462
	{
sl@0
  1463
	// Start an asynchronous read
sl@0
  1464
	TInt cmdLen=Min(TInt(iCmdLength-iCmdInOffset),TInt(KMaxBytesPerRead-iSectBufOffset)); // Leave it on sector boundary if another read required
sl@0
  1465
	iCmdEndOffset=iCmdInOffset+cmdLen;	// Marks point when transfer is complete
sl@0
  1466
	iSectBufPtr=&iSectorBuf[0];
sl@0
  1467
	iCardStatus=ECardRead;
sl@0
  1468
	__TRACE_TIMING(0x102);
sl@0
  1469
	return ReadSectorsCommand(iNextSector,iSectBufOffset,cmdLen);	// Sector number can't exceed 32bits
sl@0
  1470
	}
sl@0
  1471
sl@0
  1472
TInt DPcCardMediaDriverAta::DoWrite()
sl@0
  1473
//
sl@0
  1474
// Write to specified area of media.
sl@0
  1475
//
sl@0
  1476
	{
sl@0
  1477
sl@0
  1478
	Int64 aPos=iCurrentReq->Pos();
sl@0
  1479
	TInt aLength=(TInt)iCurrentReq->Length();
sl@0
  1480
	TInt err;
sl@0
  1481
#if (defined(_DEBUG) || defined(SHOW_CARD_ERRORS))
sl@0
  1482
	iDbgPos=(TUint)aPos;
sl@0
  1483
	iDbgLen=aLength;
sl@0
  1484
#endif
sl@0
  1485
	err=CheckDevice(ETrue);
sl@0
  1486
	if (err==KErrNone)
sl@0
  1487
		{
sl@0
  1488
		iDriveChunk.SetupChunkHw(); // Enable our h/w chunk
sl@0
  1489
		TUint sectorBufOffset=(TUint)aPos&(~KAtaSectorMask);
sl@0
  1490
		Int64 firstSector=(aPos>>KAtaSectorShift);
sl@0
  1491
		iCmdLength=aLength;
sl@0
  1492
sl@0
  1493
		// for unaligned writes, first need to read the first and/or last sector
sl@0
  1494
		err=SectorBoundaryReadCheck((TUint)firstSector,sectorBufOffset,aPos+iCmdLength);
sl@0
  1495
		if (err==KErrNone) // Sector number can't exceed 32bits
sl@0
  1496
			{
sl@0
  1497
			// Time to actually start the write. First alter the current consumption 
sl@0
  1498
			// and save the data required to complete the write (in the ISR)
sl@0
  1499
			SetCurrentConsumption(KWriteCurrentInMilliAmps);
sl@0
  1500
			iSectBufOffset=sectorBufOffset;
sl@0
  1501
			iCmdInOffset=0;
sl@0
  1502
			iCmdOutOffset=0;		// Progress monitor - data delivered to card
sl@0
  1503
			iNextSector=(TUint)firstSector;
sl@0
  1504
			iCardStatus=ECardWrite;
sl@0
  1505
			err=InitiateAsyncWrite();
sl@0
  1506
			if (err==KErrNone)
sl@0
  1507
				return KErrNone;
sl@0
  1508
			SetCurrentConsumption(KIdleCurrentInMilliAmps);
sl@0
  1509
			}
sl@0
  1510
		iCardStatus=ECardIdle;
sl@0
  1511
		if (!Kern::PowerGood())
sl@0
  1512
			err=KErrAbort; // If emergency power down - return abort rather than anything else.
sl@0
  1513
		else if (!iSocket->CardIsReady())
sl@0
  1514
			err=KErrNotReady; // If media change - return not ready rather than anything else.
sl@0
  1515
		}
sl@0
  1516
sl@0
  1517
#if (defined(_DEBUG) || defined(SHOW_CARD_ERRORS))
sl@0
  1518
	__KTRACE_CARD_ERROR(KPBUSDRV,Kern::Printf("<Ata:Write(L:%d P:%xH)-%d",iDbgLen,iDbgPos,err));
sl@0
  1519
	iDbgLastError=err;
sl@0
  1520
#endif
sl@0
  1521
	return err;
sl@0
  1522
	}
sl@0
  1523
sl@0
  1524
TInt DPcCardMediaDriverAta::InitiateAsyncWrite()
sl@0
  1525
	{
sl@0
  1526
	iCmdOutOffset=iCmdInOffset;
sl@0
  1527
	TInt remain=iCmdLength-iCmdInOffset;
sl@0
  1528
	TInt cmdLen=Min(remain, KMaxBytesPerWrite-iSectBufOffset);
sl@0
  1529
	TInt sectCount=(cmdLen+iSectBufOffset+KAtaSectorSize-1)>>KAtaSectorShift;
sl@0
  1530
	iCmdEndOffset=iCmdOutOffset+cmdLen;
sl@0
  1531
	iSectBufPtr=iSectorBuf;
sl@0
  1532
	TUint8* pB=iSectorBuf;
sl@0
  1533
	TInt r=KErrNone;
sl@0
  1534
	if (iCardStatus==ECardWrite)
sl@0
  1535
		{
sl@0
  1536
		if (iLastSectorBufUsed && cmdLen==remain)
sl@0
  1537
			{
sl@0
  1538
			// load data for sectors other than last into sector buffer
sl@0
  1539
			TInt lengthExcludingLastSector=cmdLen &~ (KAtaSectorSize-1);
sl@0
  1540
			if (lengthExcludingLastSector==cmdLen)
sl@0
  1541
				lengthExcludingLastSector-=KAtaSectorSize;
sl@0
  1542
			if (lengthExcludingLastSector)
sl@0
  1543
				{
sl@0
  1544
				r=LoadSectBufferFromSrc(lengthExcludingLastSector,iSectorBuf+iSectBufOffset);
sl@0
  1545
				if (r!=KErrNone)
sl@0
  1546
					return r;
sl@0
  1547
				iCmdInOffset+=lengthExcludingLastSector;	// make sure we get right data for last sector
sl@0
  1548
				}
sl@0
  1549
			else
sl@0
  1550
				pB=iLastSectorBuf;
sl@0
  1551
			// load last sector data into last sector buffer
sl@0
  1552
			r=LoadSectBufferFromSrc(cmdLen-lengthExcludingLastSector,iLastSectorBuf);
sl@0
  1553
			if (r!=KErrNone)
sl@0
  1554
				return r;
sl@0
  1555
			iCmdInOffset+=(cmdLen-lengthExcludingLastSector);
sl@0
  1556
			}
sl@0
  1557
		else
sl@0
  1558
			{
sl@0
  1559
			// Load the the data from source in one go
sl@0
  1560
			r=LoadSectBufferFromSrc(cmdLen,iSectorBuf+iSectBufOffset);
sl@0
  1561
			if (r!=KErrNone)
sl@0
  1562
				return r;
sl@0
  1563
			iCmdInOffset+=cmdLen;
sl@0
  1564
			}
sl@0
  1565
		}
sl@0
  1566
	else
sl@0
  1567
		iCmdInOffset+=cmdLen;	// format command
sl@0
  1568
	r=InCritical();		// this returns KErrNotReady if we are about to do postponed media change or power down
sl@0
  1569
	if (r==KErrNone)
sl@0
  1570
		{
sl@0
  1571
		r=InitiateWriteCommand(iNextSector,sectCount,pB);
sl@0
  1572
		__KTRACE_OPT(KPBUSDRV,Kern::Printf("InitWrCmd ret %d",r));
sl@0
  1573
		if (iCardStatus==ECardWrite)
sl@0
  1574
			iSectBufPtr+=KAtaSectorSize;
sl@0
  1575
		}
sl@0
  1576
	if (r!=KErrNone)
sl@0
  1577
		{
sl@0
  1578
		if (!Kern::PowerGood())
sl@0
  1579
			r=KErrAbort; // If emergency power down - return abort rather than anything else.
sl@0
  1580
		else if (!iSocket->CardIsReady())
sl@0
  1581
			r=KErrNotReady; // If media change - return not ready rather than anything else.
sl@0
  1582
		EndInCritical();
sl@0
  1583
		}
sl@0
  1584
	return r;
sl@0
  1585
	}
sl@0
  1586
sl@0
  1587
TInt DPcCardMediaDriverAta::DoFormat()
sl@0
  1588
//
sl@0
  1589
// Format the specified area of the media. 
sl@0
  1590
//
sl@0
  1591
	{
sl@0
  1592
	
sl@0
  1593
	Int64 aPos=iCurrentReq->Pos();
sl@0
  1594
	TInt aLength=(TInt)iCurrentReq->Length();
sl@0
  1595
	TInt err;
sl@0
  1596
#if (defined(_DEBUG) || defined(SHOW_CARD_ERRORS))
sl@0
  1597
	iDbgPos=(TUint)aPos;
sl@0
  1598
	iDbgLen=aLength;
sl@0
  1599
#endif
sl@0
  1600
	err=CheckDevice(ETrue);
sl@0
  1601
	if (err==KErrNone)
sl@0
  1602
		{
sl@0
  1603
		iDriveChunk.SetupChunkHw(); // Enable our h/w chunk
sl@0
  1604
		memset(iSectorBuf,0xff,KAtaSectorSize);
sl@0
  1605
		Int64 firstSector=(aPos>>KAtaSectorShift);
sl@0
  1606
		TInt sectCount=(aLength+KAtaSectorSizeMinusOne)>>KAtaSectorShift;
sl@0
  1607
		iCmdLength=(sectCount<<KAtaSectorShift);
sl@0
  1608
		sectCount=Min(KMaxSectorsPerFormat,(aLength+KAtaSectorSizeMinusOne)>>KAtaSectorShift);
sl@0
  1609
		SetCurrentConsumption(KWriteCurrentInMilliAmps);
sl@0
  1610
sl@0
  1611
		iLastSectorBufUsed=EFalse;
sl@0
  1612
		iCmdInOffset=0;
sl@0
  1613
		iCmdOutOffset=0;		// Progress monitor - data delivered to card
sl@0
  1614
		iSectBufOffset=0;
sl@0
  1615
		iSectBufPtr=&iSectorBuf[0];
sl@0
  1616
		iNextSector=(TUint)firstSector;
sl@0
  1617
		iCardStatus=ECardFormat;
sl@0
  1618
		err=InitiateAsyncWrite();
sl@0
  1619
		if (err==KErrNone)
sl@0
  1620
			return KErrNone;
sl@0
  1621
sl@0
  1622
		iCardStatus=ECardIdle;
sl@0
  1623
		SetCurrentConsumption(KIdleCurrentInMilliAmps);
sl@0
  1624
sl@0
  1625
		if (!Kern::PowerGood())
sl@0
  1626
			err=KErrAbort; // If emergency power down - return abort rather than anything else.
sl@0
  1627
		else if (!iSocket->CardIsReady())
sl@0
  1628
			err=KErrNotReady; // If media change - return not ready rather than anything else.
sl@0
  1629
		}
sl@0
  1630
sl@0
  1631
#if (defined(_DEBUG) || defined(SHOW_CARD_ERRORS))
sl@0
  1632
	__KTRACE_CARD_ERROR(KPBUSDRV,Kern::Printf("<Ata:Format(L:%d P:%xH)-%d",iDbgLen,iDbgPos,err));
sl@0
  1633
	iDbgLastError=err;
sl@0
  1634
#endif
sl@0
  1635
	return err;
sl@0
  1636
	}
sl@0
  1637
sl@0
  1638
void DPcCardMediaDriverAta::Close()
sl@0
  1639
//
sl@0
  1640
// Close the media driver - also called on media change
sl@0
  1641
//
sl@0
  1642
	{
sl@0
  1643
sl@0
  1644
	__KTRACE_OPT(KPBUSDRV,Kern::Printf(">Ata:Close"));
sl@0
  1645
	EndInCritical();
sl@0
  1646
	Complete(KErrNotReady);
sl@0
  1647
	DoClose();
sl@0
  1648
	DMediaDriver::Close();
sl@0
  1649
	}
sl@0
  1650
sl@0
  1651
void DPcCardMediaDriverAta::DoClose()
sl@0
  1652
//
sl@0
  1653
// Close the media driver
sl@0
  1654
//
sl@0
  1655
	{
sl@0
  1656
sl@0
  1657
	__KTRACE_OPT(KPBUSDRV,Kern::Printf(">Ata:DoClose"));
sl@0
  1658
	iCardIntCallBack.Remove();
sl@0
  1659
	iDriveChunk.Close();
sl@0
  1660
	if (iCardFuncNum>=0)
sl@0
  1661
		{
sl@0
  1662
		iSocket->ReleaseConfig(iCardFuncNum,this);
sl@0
  1663
		iCardFuncNum=-1;
sl@0
  1664
		}
sl@0
  1665
	Reset();
sl@0
  1666
	__KTRACE_CARD_ERROR(KPBUSDRV,Kern::Printf("<Ata:DoClose(%d)",iDbgLastError));
sl@0
  1667
	}
sl@0
  1668
sl@0
  1669
void DPcCardMediaDriverAta::Reset()
sl@0
  1670
	{
sl@0
  1671
	__KTRACE_OPT(KPBUSDRV,Kern::Printf(">Ata:Reset"));
sl@0
  1672
	iBusyTimeout.Cancel();			// In case its currently queued
sl@0
  1673
	iCardIreqDfc.Cancel();			// In case its currently queued
sl@0
  1674
	iTimerDfc.Cancel();
sl@0
  1675
	iCardStatus=ECardIdle;
sl@0
  1676
	SetCurrentConsumption(0);
sl@0
  1677
	}
sl@0
  1678
sl@0
  1679
#ifdef KLOCDRV
sl@0
  1680
void DebugDump(const TMBRPartitionEntry& a)
sl@0
  1681
	{
sl@0
  1682
	Kern::Printf("BootInd =%02x StartHead=%02x StartSect=%02x StartCyl=%02x",
sl@0
  1683
			a.iX86BootIndicator, a.iStartHead, a.iStartSector, a.iStartCylinder);
sl@0
  1684
	Kern::Printf("PartType=%02x EndHead  =%02x EndSect  =%02x EndCyl  =%02x",
sl@0
  1685
			a.iPartitionType, a.iEndHead, a.iEndSector, a.iEndCylinder);
sl@0
  1686
	Kern::Printf("FirstSect=%08x NumSectors=%08x", a.iFirstSector, a.iNumSectors);
sl@0
  1687
	}
sl@0
  1688
sl@0
  1689
void DebugDump(const TPartitionInfo& a)
sl@0
  1690
	{
sl@0
  1691
	Kern::Printf("PartitionInfo: (C:%d)",a.iPartitionCount);
sl@0
  1692
	TInt i;
sl@0
  1693
	for (i=0; i<KMaxPartitionEntries; ++i)
sl@0
  1694
		{
sl@0
  1695
		const TPartitionEntry& e=a.iEntry[i];
sl@0
  1696
		Kern::Printf("   Partition %d: B=%lxH L=%lxH I=%04x T=%04x", i, e.iPartitionBaseAddr,
sl@0
  1697
						e.iPartitionLen, e.iBootIndicator, e.iPartitionType );
sl@0
  1698
		}
sl@0
  1699
	}
sl@0
  1700
#endif
sl@0
  1701
sl@0
  1702
void SetPartitionEntry(TPartitionEntry* aDest, const TMBRPartitionEntry* aSrc)
sl@0
  1703
//
sl@0
  1704
// Set the partition entry details
sl@0
  1705
//
sl@0
  1706
	{
sl@0
  1707
sl@0
  1708
	aDest->iPartitionBaseAddr=aSrc->iFirstSector;
sl@0
  1709
	aDest->iPartitionBaseAddr<<=KAtaSectorShift;
sl@0
  1710
	aDest->iPartitionLen=aSrc->iNumSectors;
sl@0
  1711
	aDest->iPartitionLen<<=KAtaSectorShift;
sl@0
  1712
	aDest->iBootIndicator=aSrc->iX86BootIndicator;
sl@0
  1713
	aDest->iPartitionType=aSrc->iPartitionType;
sl@0
  1714
	}
sl@0
  1715
sl@0
  1716
TInt DPcCardMediaDriverAta::PartitionInfo(TPartitionInfo& anInfo)
sl@0
  1717
//
sl@0
  1718
// Return partition information on the media.
sl@0
  1719
//
sl@0
  1720
	{
sl@0
  1721
sl@0
  1722
	__KTRACE_OPT(KPBUSDRV,Kern::Printf(">Ata:PartitionInfo"));
sl@0
  1723
	if (iSocket->CardIsReadyAndVerified()!=KErrNone)
sl@0
  1724
		return(KErrNotReady);
sl@0
  1725
	TInt partitionCount=anInfo.iPartitionCount=0;
sl@0
  1726
sl@0
  1727
	// Read the first sector and check for a Master Boot Record
sl@0
  1728
	TInt err;
sl@0
  1729
	if ((err=SectorRead(0,&iSectorBuf[0]))!=KErrNone)
sl@0
  1730
		return(err);
sl@0
  1731
	if (*(TUint16*)(&iSectorBuf[KMBRSignatureOffset])!=KMBRSignature)
sl@0
  1732
		return(KErrCorrupt);
sl@0
  1733
sl@0
  1734
	// Move the partition entries to a 4 byte boundary
sl@0
  1735
	memmove(&iSectorBuf[0],&iSectorBuf[KMBRFirstPartitionOffset],(sizeof(TMBRPartitionEntry)*KMBRMaxPrimaryPartitions));
sl@0
  1736
sl@0
  1737
	// Search for a x86 default boot partition - let this be the first
sl@0
  1738
	TMBRPartitionEntry *pe=(TMBRPartitionEntry*)(&iSectorBuf[0]);
sl@0
  1739
	TInt i;
sl@0
  1740
	TInt defaultPartitionNumber=-1;
sl@0
  1741
	for (i=0;i<KMBRMaxPrimaryPartitions;i++,pe++)
sl@0
  1742
		{
sl@0
  1743
		if (pe->IsDefaultBootPartition())
sl@0
  1744
			{
sl@0
  1745
			SetPartitionEntry(anInfo.iEntry, pe);
sl@0
  1746
			defaultPartitionNumber=i;
sl@0
  1747
			iHiddenSectors=pe->iFirstSector;
sl@0
  1748
			partitionCount++;
sl@0
  1749
			break;
sl@0
  1750
			}
sl@0
  1751
		}
sl@0
  1752
sl@0
  1753
	// Now add any other partitions
sl@0
  1754
	pe=(TMBRPartitionEntry*)(&iSectorBuf[0]);	// Reset it
sl@0
  1755
	for (i=0;i<KMBRMaxPrimaryPartitions;i++,pe++)
sl@0
  1756
		{
sl@0
  1757
		__KTRACE_OPT(KLOCDRV, Kern::Printf("Partition %d:",i));
sl@0
  1758
		__KTRACE_OPT(KLOCDRV, DebugDump(*pe));
sl@0
  1759
		if (defaultPartitionNumber==i)
sl@0
  1760
			continue;	// Already sorted
sl@0
  1761
		if (pe->IsValidDosPartition() || pe->IsValidFAT32Partition())
sl@0
  1762
			{
sl@0
  1763
			SetPartitionEntry(anInfo.iEntry+partitionCount, pe);
sl@0
  1764
			partitionCount++;
sl@0
  1765
			}
sl@0
  1766
		}
sl@0
  1767
	anInfo.iPartitionCount=partitionCount;
sl@0
  1768
	anInfo.iMediaSizeInBytes=TotalSizeInBytes();
sl@0
  1769
sl@0
  1770
	__KTRACE_OPT(KLOCDRV, DebugDump(anInfo));
sl@0
  1771
sl@0
  1772
	PartitionInfoComplete(KErrNone);
sl@0
  1773
	return KErrNone;
sl@0
  1774
	}
sl@0
  1775
sl@0
  1776
TInt DPcCardMediaDriverAta::Caps(TLocalDriveCapsV6& aInfo)
sl@0
  1777
//
sl@0
  1778
// Return the capabilities of the media
sl@0
  1779
//
sl@0
  1780
	{
sl@0
  1781
	aInfo.iType=EMediaHardDisk;
sl@0
  1782
	aInfo.iConnectionBusType=EConnectionBusInternal;
sl@0
  1783
	aInfo.iDriveAtt=KDriveAttLocal|KDriveAttRemovable;
sl@0
  1784
	aInfo.iMediaAtt=KMediaAttFormattable;
sl@0
  1785
	aInfo.iFileSystemId=KDriveFileSysFAT;
sl@0
  1786
	aInfo.iHiddenSectors=iHiddenSectors;
sl@0
  1787
	aInfo.iBlockSize=KAtaSectorSize;
sl@0
  1788
	return KErrCompletion;	// synchronous completion
sl@0
  1789
	}
sl@0
  1790
sl@0
  1791
DECLARE_STANDARD_PDD()
sl@0
  1792
	{
sl@0
  1793
	return new DPhysicalDeviceMediaAta;
sl@0
  1794
	}
sl@0
  1795