os/kernelhwsrv/kernel/eka/drivers/medata/pccd_ata.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/kernelhwsrv/kernel/eka/drivers/medata/pccd_ata.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,1795 @@
     1.4 +// Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of the License "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +// e32\drivers\medata\pccd_ata.cpp
    1.18 +// 
    1.19 +//
    1.20 +
    1.21 +#include "pbusmedia.h"
    1.22 +#include "platform.h"
    1.23 +#include "ata.h"
    1.24 +
    1.25 +const TInt KErrBadDrqOnRead=-64;
    1.26 +const TInt KErrBadDrqOnWrite=-65;
    1.27 +const TInt KErrBadDrq=-66;
    1.28 +const TInt KErrAta=-67;
    1.29 +const TInt KErrBadPccdConfig=-68;
    1.30 +//const TInt KErrDriveChunkNotOpen=-69;
    1.31 +
    1.32 +const TInt KAtaDriverPriority=KMediaDriverPriorityNormal;
    1.33 +//const TInt KAtaDriverPriority=KMediaDriverPriorityHigh;
    1.34 +
    1.35 +_LIT(KPddName, "Media.Ata");
    1.36 +//_LIT(KPddName, "Media.Ata2");
    1.37 +
    1.38 +// One of these
    1.39 +#define SELECT_CONTIGUOUS_IO_CONFIG
    1.40 +//#define SELECT_PRIMARY_IO_CONFIG
    1.41 +//#define SELECT_MEMORY_CONFIG
    1.42 +
    1.43 +//#define FORCE_8BIT_ACCESSES
    1.44 +
    1.45 +// Special debug options
    1.46 +//#define SHOW_CARD_ERRORS
    1.47 +//#define DEBUG_WITH_HW_TRIGGER
    1.48 +//#define COUNT_TIMEOUTS
    1.49 +
    1.50 +#if (defined(SHOW_CARD_ERRORS))
    1.51 +#define __KTRACE_CARD_ERROR(a,p) {p;}
    1.52 +#elif (defined(_DEBUG))
    1.53 +#define __KTRACE_CARD_ERROR(a,p) {if((KDebugNum(a)))p;}
    1.54 +#else
    1.55 +#define __KTRACE_CARD_ERROR(a,p)
    1.56 +#endif
    1.57 +
    1.58 +#include <pccard.h>
    1.59 +
    1.60 +const TInt KMaxSectorsPerRead=32;
    1.61 +const TInt KMaxSectorsPerWrite=8;				 
    1.62 +const TInt KMaxSectorsPerFormat=8;				 
    1.63 +const TInt KMaxBytesPerRead=(KMaxSectorsPerRead<<KAtaSectorShift);
    1.64 +const TInt KMaxBytesPerWrite=(KMaxSectorsPerWrite<<KAtaSectorShift);
    1.65 +
    1.66 +// Sector buffer size must be a multiple of sector size and at least as large
    1.67 +// as KMaxSectorsPerWrite.
    1.68 +const TInt KSectBufSizeInSectors=8;
    1.69 +const TInt KSectBufSizeInBytes=(KSectBufSizeInSectors<<KAtaSectorShift);
    1.70 +const TInt KSectBufSizeInBytesMinusOneSector=(KSectBufSizeInBytes-KAtaSectorSize);
    1.71 +
    1.72 +const TInt KIdleCurrentInMilliAmps=1; 
    1.73 +const TInt KReadCurrentInMilliAmps=39;
    1.74 +const TInt KWriteCurrentInMilliAmps=46;
    1.75 +
    1.76 +const TInt KNotBusySyncTimeout=5;
    1.77 +const TInt KNotBusySyncRetryCount=10;
    1.78 +const TInt KDriveReadySyncTimeout=5;
    1.79 +
    1.80 +#ifdef _DEBUG
    1.81 +const TInt KNotBusyTestInterval=30;		// Check for not-busy once every 30ms
    1.82 +const TInt KBusyTimeOut=67;				// Timeout after this many tests (67*30ms=2010ms)
    1.83 +#else
    1.84 +const TInt KNotBusyTestInterval=5;		// Check for not-busy once every 5ms
    1.85 +const TInt KBusyTimeOut=400;			// Timeout after this many tests (400*5ms=2010ms)
    1.86 +#endif
    1.87 +
    1.88 +class DPhysicalDeviceMediaAta : public DPhysicalDevice
    1.89 +	{
    1.90 +public:
    1.91 +	DPhysicalDeviceMediaAta();
    1.92 +	virtual TInt Install();
    1.93 +	virtual void GetCaps(TDes8& aDes) const;
    1.94 +	virtual TInt Create(DBase*& aChannel, TInt aMediaId, const TDesC8* anInfo, const TVersion& aVer);
    1.95 +	virtual TInt Validate(TInt aDeviceType, const TDesC8* anInfo, const TVersion& aVer);
    1.96 +	virtual TInt Info(TInt aFunction, TAny* a1);
    1.97 +	};
    1.98 +
    1.99 +class DPcCardMediaDriverAta : public DMediaDriver
   1.100 +	{
   1.101 +public:
   1.102 +	DPcCardMediaDriverAta(TInt aMediaId);
   1.103 +	virtual TInt Request(TLocDrvRequest& aRequest);
   1.104 +	virtual TInt PartitionInfo(TPartitionInfo& anInfo);
   1.105 +	virtual void NotifyPowerDown();
   1.106 +	virtual void NotifyEmergencyPowerDown();
   1.107 +	virtual void Close();
   1.108 +public:
   1.109 +	enum TCardStatus {ECardIdle,ECardRead,ECardWrite,ECardFormat};
   1.110 +	inline TUint8 AtaRegister8(TUint aReg);
   1.111 +	inline void SetAtaRegister8(TUint8 aValue,TUint aReg);
   1.112 +	void ModifyAtaRegister8(TUint aClearMask,TUint aSetMask,TUint aReg);
   1.113 +	void SelectDrive(TAtaDriveSelect aDrive);
   1.114 +	TBool WaitForNotBusy();
   1.115 +	TBool DriveReadyForCommand(TInt aDrive);
   1.116 +	void SetLbaSectorAddress(TUint aSector);
   1.117 +	void SetChsSectorAddress(TUint aSector);
   1.118 +	TInt IssueAtaCommand(TUint8 aCmd,TUint aFirstSector,TInt aSectorCount);
   1.119 +	TInt EmptySectBufferToTrg(TUint8 *aSrc,TUint aTrgOffset,TInt aLen);
   1.120 +	TInt LoadSectBufferFromSrc(TInt aLen, TUint8* aBuf);
   1.121 +	TInt LoadSectBufferFromDrive(TAny *aBuf);
   1.122 +	TInt EmptySectBufferToDrive(TUint8 *aBuf);
   1.123 +	TInt TransferSectBufferFromDrive(TAny *aBuf);
   1.124 +	TInt FinishCommand();
   1.125 +	TInt CheckForError();
   1.126 +	TInt ProcessError(TInt anError);
   1.127 +	TInt SectorBoundaryReadCheck(TUint aStartSector,TUint aStartSectOffset,Int64 anEndPos);
   1.128 +	TInt SectorRead(TUint aFirstSector,TUint8 *aBuf,TInt aSectorCount=1,TUint8 aCmd=KAtaCmdReadSectors);
   1.129 +	TInt CheckDevice(TBool aCheckPower);
   1.130 +	TInt InitiateWriteCommand(TUint aFirstSector,TInt aSectorCount,TUint8 *aSectBuffer);
   1.131 +	TInt ReadSectorsCommand(TUint aFirstSector,TUint aBufOffset,TInt aLen);
   1.132 +	TInt IdentifyDrive();
   1.133 +	void DumpIdentifyDriveInfo();
   1.134 +	TInt ConfigAutoPowerDown();
   1.135 +	TInt Open();
   1.136 +	TInt DoOpen();
   1.137 +	void DoClose();
   1.138 +	void Reset();
   1.139 +	TBool CardPoweredDown();
   1.140 +	void IncrementSectBufPtr();
   1.141 +	static void CardIreqDfcFunction(TAny* aPtr);
   1.142 +	static void TimerDfcFunction(TAny* aPtr);
   1.143 +	static void AsyncBusyTimerCallBack(TAny* aMediaDriver);
   1.144 +	static void SyncBusyTimerCallBack(TAny* aBusyFlag);
   1.145 +	static void CardIntCallBack(TAny* aPtr, TInt anId);
   1.146 +	TBool DoCardNotBusy(TInt &anErr);
   1.147 +	TBool CmdDfc();
   1.148 +	TBool DoCmdDfc(TInt &anErr);
   1.149 +	void Complete(TInt anError);
   1.150 +	TInt Caps(TLocalDriveCapsV6& anInfo);
   1.151 +	TInt DoRead();
   1.152 +	TInt DoWrite();
   1.153 +	TInt DoFormat();
   1.154 +	TInt InitiateAsyncRead();
   1.155 +	TInt InitiateAsyncWrite();
   1.156 +public:
   1.157 +	DPcCardSocket* iSocket;
   1.158 +	TLocDrvRequest* iCurrentReq;
   1.159 +	TPBusCallBack iCardIntCallBack;
   1.160 +	RPccdWindow iDriveChunk;
   1.161 +	TPccdMemType iMemoryType;
   1.162 +	TDriveParameters iDriveInfo;
   1.163 +	NTimer iBusyTimeout;
   1.164 +	TDfc iCardIreqDfc;
   1.165 +	TDfc iTimerDfc;
   1.166 +	TInt iNotBusyTickCount;
   1.167 +	TInt iCommandError;
   1.168 +	TCardStatus iCardStatus;
   1.169 +	TUint iCmdInOffset; 	// Progress counter for data received from src device
   1.170 +	TUint iCmdOutOffset;	// Progress counter for data delivered to target device
   1.171 +	TUint iCmdEndOffset;	// Marks point when transfer associated with command is complete
   1.172 +	TUint iCmdLength;		// Transfer length remaining
   1.173 +	TUint iNextSector;		// Next sector to transfer
   1.174 +	TUint8 *iSectBufPtr;	// Progress counter for tranfering data between card and sector buffer
   1.175 +	TUint iSectBufOffset;	// Offset within sector buffer to start of data involved in command (Reads only)
   1.176 +	TBool iLastSectorBufUsed;
   1.177 +	TUint iHiddenSectors;
   1.178 +	TInt iCardFuncNum;
   1.179 +	TUint8 iSectorBuf[KSectBufSizeInBytes]; // Keep on 4byte boundary - put this last
   1.180 +	TUint8 iLastSectorBuf[KAtaSectorSize];	// Holds last sector data for unaligned write
   1.181 +#if (defined(_DEBUG) || defined(SHOW_CARD_ERRORS))
   1.182 +	TInt iDbgLastError;
   1.183 +	TInt iDbgPos;
   1.184 +	TInt iDbgLen;
   1.185 +#endif
   1.186 +#ifdef COUNT_TIMEOUTS
   1.187 +	TInt iInts;
   1.188 +	TInt iTimeouts;
   1.189 +	TInt iImmediateNotBusy;
   1.190 +	TInt iChainedReads;
   1.191 +	TInt iChainedWrites;
   1.192 +	TBool iNewTimeOut;
   1.193 +	TInt iIndex;
   1.194 +	TInt iInfo[8];
   1.195 +#endif
   1.196 +	};
   1.197 +
   1.198 +void DPcCardMediaDriverAta::Complete(TInt anError)
   1.199 +	{
   1.200 +	__KTRACE_OPT(KFAIL,Kern::Printf("mdrqc %08x %d",iCurrentReq,anError));
   1.201 +#ifdef COUNT_TIMEOUTS
   1.202 +	if (iNewTimeOut)
   1.203 +		{
   1.204 +		iNewTimeOut=EFalse;
   1.205 +		Kern::Printf("I=%d T=%d M=%d CR=%d CW=%d",iInts,iTimeouts,iImmediateNotBusy,iChainedReads,iChainedWrites);
   1.206 +		TInt i;
   1.207 +		for (i=0; i<iIndex; i+=2)
   1.208 +			Kern::Printf("%d: %08x %08x",i,iInfo[i],iInfo[i+1]);
   1.209 +		iIndex=0;
   1.210 +		}
   1.211 +#endif
   1.212 +	TLocDrvRequest* pR=iCurrentReq;
   1.213 +	if (pR)
   1.214 +		{
   1.215 +		iCurrentReq=NULL;
   1.216 +		DMediaDriver::Complete(*pR,anError);
   1.217 +		}
   1.218 +	}
   1.219 +
   1.220 +inline TUint8 DPcCardMediaDriverAta::AtaRegister8(TUint aReg)
   1.221 +//
   1.222 +// Read from an 8 bit ATA register
   1.223 +//
   1.224 +	{
   1.225 +
   1.226 +	return iDriveChunk.Read8(aReg);
   1.227 +	}
   1.228 +
   1.229 +inline void DPcCardMediaDriverAta::SetAtaRegister8(TUint8 aValue,TUint aReg)
   1.230 +//
   1.231 +// Write to an 8 bit ATA register
   1.232 +//
   1.233 +	{
   1.234 +
   1.235 +	iDriveChunk.Write8(aReg,aValue);
   1.236 +	}
   1.237 +
   1.238 +void DPcCardMediaDriverAta::ModifyAtaRegister8(TUint aClearMask,TUint aSetMask,TUint aReg)
   1.239 +//
   1.240 +// Modify an 8 bit ATA register
   1.241 +//
   1.242 +	{
   1.243 +
   1.244 +	SetAtaRegister8((TUint8)((AtaRegister8(aReg)&(~aClearMask))|aSetMask),aReg);
   1.245 +	}
   1.246 +
   1.247 +void DPcCardMediaDriverAta::SelectDrive(TAtaDriveSelect aDrive)
   1.248 +//
   1.249 +// Modify an 8 bit ATA register
   1.250 +//
   1.251 +	{
   1.252 +
   1.253 +	ModifyAtaRegister8(KAtaDrvHeadDrive1,(0xA0|aDrive),KAtaSelectDriveHeadRdWr8);
   1.254 +	}
   1.255 +
   1.256 +TBool DPcCardMediaDriverAta::WaitForNotBusy()
   1.257 +//
   1.258 +// Poll busy flag (while card accesses the data buffer and command register). 
   1.259 +// 8mS timeout.
   1.260 +//
   1.261 +	{
   1.262 +
   1.263 +	// Before we start a timed loop, just check it isn't already not busy
   1.264 +	__KTRACE_OPT(KPBUSDRV,Kern::Printf("WfnB"));
   1.265 +	if (!(AtaRegister8(KAtaStatusRd8)&KAtaStatusBusy))
   1.266 +		return(ETrue);
   1.267 +#if (defined(_DEBUG) || defined(SHOW_CARD_ERRORS))
   1.268 +	TUint c=NKern::TickCount();
   1.269 +#endif
   1.270 +	volatile TBool timedOut=EFalse;
   1.271 +	NTimer busyTimeout(SyncBusyTimerCallBack,(TAny*)&timedOut);
   1.272 +	busyTimeout.OneShot(NKern::TimerTicks(KNotBusySyncTimeout));
   1.273 +	FOREVER
   1.274 +		{
   1.275 +		if (!(AtaRegister8(KAtaStatusRd8)&KAtaStatusBusy)||timedOut)
   1.276 +			break;
   1.277 +		}
   1.278 +	if (!timedOut)
   1.279 +		busyTimeout.Cancel();
   1.280 +	else
   1.281 +		{
   1.282 +		TInt retry=KNotBusySyncRetryCount;
   1.283 +		while ((AtaRegister8(KAtaStatusRd8)&KAtaStatusBusy) && retry)
   1.284 +			{
   1.285 +			NKern::Sleep(1);
   1.286 +			retry--;
   1.287 +			}
   1.288 +		}
   1.289 +	TBool ret=(AtaRegister8(KAtaStatusRd8) & KAtaStatusBusy);
   1.290 +#if (defined(_DEBUG) || defined(SHOW_CARD_ERRORS))
   1.291 +	c=NKern::TickCount()-c;
   1.292 +	if (ret)
   1.293 +		{
   1.294 +		__KTRACE_CARD_ERROR(KPBUSDRV,Kern::Printf("<Ata:WaitForNotBusy-timeout(%xH) %d ms",AtaRegister8(KAtaStatusRd8),c));
   1.295 + 		}
   1.296 +	else
   1.297 +		{
   1.298 +		__KTRACE_CARD_ERROR(KPBUSDRV,Kern::Printf("<Ata:WaitForNotBusy-OK %d ms",c));
   1.299 +		}
   1.300 +#endif
   1.301 +	return(!ret);
   1.302 +	}
   1.303 +
   1.304 +TBool DPcCardMediaDriverAta::DriveReadyForCommand(TInt aDrive)
   1.305 +//
   1.306 +// Wait until selected drive is able to accept a command (5ms timeout).
   1.307 +//					
   1.308 +	{
   1.309 +
   1.310 +	// Select the drive were waiting on 
   1.311 +	SelectDrive((aDrive==1)?ESelectDrive1:ESelectDrive0);
   1.312 +	if (!WaitForNotBusy())
   1.313 +		return(EFalse);
   1.314 +
   1.315 +	volatile TBool timedOut=EFalse;
   1.316 +	NTimer busyTimeout(SyncBusyTimerCallBack,(TAny*)&timedOut);
   1.317 +	busyTimeout.OneShot(NKern::TimerTicks(KDriveReadySyncTimeout));
   1.318 +	FOREVER
   1.319 +		{
   1.320 +		if (AtaRegister8(KAtaStatusRd8)&KAtaStatusRdy||timedOut)
   1.321 +			break;
   1.322 +		}
   1.323 +	if (!timedOut)
   1.324 +		busyTimeout.Cancel();
   1.325 +	TBool ret=(AtaRegister8(KAtaStatusRd8) & KAtaStatusRdy);
   1.326 +#if (defined(_DEBUG) || defined(SHOW_CARD_ERRORS))
   1.327 +	if (!ret)
   1.328 +		__KTRACE_CARD_ERROR(KPBUSDRV,Kern::Printf("<Ata:DriveReadyForCommand-Fail(%xH)",AtaRegister8(KAtaStatusRd8)));
   1.329 +#endif
   1.330 +	return(ret);
   1.331 +	}
   1.332 +
   1.333 +void DPcCardMediaDriverAta::SetLbaSectorAddress(TUint aSector)
   1.334 +//
   1.335 +// Setup the sector address ATA registers (LBA mode)
   1.336 +//
   1.337 +	{
   1.338 +	__KTRACE_OPT(KPBUSDRV,Kern::Printf(">Ata:SetLbaSectorAddress (LBA: %xH)",aSector));
   1.339 +
   1.340 +	SetAtaRegister8((TUint8)aSector,KAtaLba7_0RdWr8);
   1.341 +	SetAtaRegister8((TUint8)(aSector>>8),KAtaLba15_8RdWr8);
   1.342 +	SetAtaRegister8((TUint8)(aSector>>16),KAtaLba23_16RdWr8);
   1.343 +	TUint8 lba27_24=(TUint8)((aSector>>24)&0x0F);
   1.344 +	ModifyAtaRegister8(KAtaDrvHeadLba27_24,(KAtaDrvHeadLbaOn|lba27_24),KAtaSelectDriveHeadRdWr8);
   1.345 +	}
   1.346 +
   1.347 +void DPcCardMediaDriverAta::SetChsSectorAddress(TUint aSector)
   1.348 +//
   1.349 +// Setup the sector address ATA registers (CHS mode)
   1.350 +//
   1.351 +	{
   1.352 +
   1.353 +	TUint cylinder=0,head=0,sector=1;
   1.354 +	if (iDriveInfo.iSectorsPerCylinder>0&&iDriveInfo.iSectorsPerTrack>0)
   1.355 +		{
   1.356 +		cylinder=aSector/iDriveInfo.iSectorsPerCylinder;
   1.357 +		TUint remainder=aSector%iDriveInfo.iSectorsPerCylinder;
   1.358 +		head=remainder/iDriveInfo.iSectorsPerTrack;
   1.359 +		sector=(remainder%iDriveInfo.iSectorsPerTrack)+1;
   1.360 +		}
   1.361 +
   1.362 +	__KTRACE_OPT(KPBUSDRV,Kern::Printf("Ata:SetChsSectorAddress (C: %xH H: %xH S: %xH)",cylinder,head,sector));
   1.363 +	SetAtaRegister8((TUint8)sector,KAtaSectorNoRdWr8);
   1.364 +	SetAtaRegister8((TUint8)cylinder,KAtaCylinderLowRdWr8);
   1.365 +	SetAtaRegister8((TUint8)(cylinder>>8),KAtaCylinderHighRdWr8);
   1.366 +	ModifyAtaRegister8((KAtaDrvHeadLbaOn|KAtaDrvHeadLba27_24),((TUint8)(head&0x0F)),KAtaSelectDriveHeadRdWr8);
   1.367 +	}
   1.368 +
   1.369 +TInt DPcCardMediaDriverAta::IssueAtaCommand(TUint8 aCmd,TUint aFirstSector,TInt aSectorCount)
   1.370 +//
   1.371 +// Issue an ATA command (Drive 0 only for now).
   1.372 +//
   1.373 +	{
   1.374 +
   1.375 +	__KTRACE_OPT(KPBUSDRV,Kern::Printf(">Ata:IssueAtaCommand(C:%x, FS:%x, SC:%x)",aCmd,aFirstSector,aSectorCount));
   1.376 +	__KTRACE_OPT(KFAIL,Kern::Printf("A%02x,%d",aCmd,aSectorCount));
   1.377 +	if (!WaitForNotBusy())
   1.378 +		return(KErrTimedOut);
   1.379 +	if (!DriveReadyForCommand(0))
   1.380 +		return KErrTimedOut;
   1.381 +	
   1.382 +	if (aSectorCount==KMaxSectorsPerCmd)
   1.383 +		aSectorCount=0;
   1.384 +	SetAtaRegister8((TUint8)aSectorCount,KAtaSectorCountRdWr8);
   1.385 +	if (iDriveInfo.iSupportsLba)
   1.386 +		SetLbaSectorAddress(aFirstSector);
   1.387 +	else
   1.388 +		SetChsSectorAddress(aFirstSector);
   1.389 +	__TRACE_TIMING(0x103);
   1.390 +	SetAtaRegister8(aCmd,KAtaCommandWr8);	// Issue the command
   1.391 +	Kern::NanoWait(400);					// Busy flag not asserted for 400ns
   1.392 +	__KTRACE_OPT(KPBUSDRV,Kern::Printf("<Ata:IssueAtaCommand"));
   1.393 +	return(KErrNone);
   1.394 +	}
   1.395 +
   1.396 +TInt DPcCardMediaDriverAta::LoadSectBufferFromDrive(TAny *aBuf)
   1.397 +//
   1.398 +// Read a sector from the ATA card
   1.399 +//
   1.400 +	{
   1.401 +
   1.402 +	if (!(AtaRegister8(KAtaStatusRd8)&KAtaStatusDrq))
   1.403 +		{
   1.404 +		__KTRACE_CARD_ERROR(KPBUSDRV,Kern::Printf(">Ata:LoadSectBufferFromDrive-Bad drq(%xH)",AtaRegister8(KAtaStatusRd8)));
   1.405 +		return KErrBadDrqOnRead;
   1.406 +		}
   1.407 +
   1.408 +	if (__IS_COMMON_MEM(iMemoryType))
   1.409 +		iDriveChunk.Read(KAtaDataRdWrWinBase16,aBuf,KAtaSectorSize); // Use 1K window
   1.410 +	else if (iMemoryType==EPccdIo16Mem)
   1.411 +		iDriveChunk.ReadHWordMultiple(KAtaDataRdWr16,aBuf,(KAtaSectorSize>>1));
   1.412 +	else
   1.413 +		iDriveChunk.ReadByteMultiple(KAtaDataRdWr8,aBuf,KAtaSectorSize); // Must be EPccdIo8Mem
   1.414 +
   1.415 +	return(KErrNone);
   1.416 +	}
   1.417 +
   1.418 +TInt DPcCardMediaDriverAta::TransferSectBufferFromDrive(TAny *aBuf)
   1.419 +//
   1.420 +// Read a sector from the ATA card
   1.421 +//
   1.422 +	{
   1.423 +
   1.424 +	if (!WaitForNotBusy())
   1.425 +		return(KErrTimedOut);
   1.426 +	return(LoadSectBufferFromDrive(aBuf));
   1.427 +	}
   1.428 +
   1.429 +TInt DPcCardMediaDriverAta::EmptySectBufferToDrive(TUint8 *aBuf)
   1.430 +//
   1.431 +// Write a sector to the ATA card.
   1.432 +//
   1.433 +	{
   1.434 +
   1.435 +	if (!(AtaRegister8(KAtaStatusRd8)&KAtaStatusDrq))
   1.436 +		{
   1.437 +		__KTRACE_CARD_ERROR(KPBUSDRV,Kern::Printf(">Ata:EmptySectBufferToDrive-Bad drq(%xH)",AtaRegister8(KAtaStatusRd8)));
   1.438 +		return KErrBadDrqOnWrite;
   1.439 +		}
   1.440 +
   1.441 +	if (__IS_COMMON_MEM(iMemoryType))
   1.442 +		iDriveChunk.Write(KAtaDataRdWrWinBase16,aBuf,KAtaSectorSize); // Use 1K window
   1.443 +	else if (iMemoryType==EPccdIo16Mem)
   1.444 +		iDriveChunk.WriteHWordMultiple(KAtaDataRdWr16,aBuf,(KAtaSectorSize>>1));
   1.445 +	else
   1.446 +		iDriveChunk.WriteByteMultiple(KAtaDataRdWr8,aBuf,KAtaSectorSize); // Must be EPccdIo8Mem
   1.447 +
   1.448 +	return(KErrNone); 
   1.449 +	}
   1.450 +
   1.451 +TInt DPcCardMediaDriverAta::FinishCommand()
   1.452 +//
   1.453 +// Called each time a command has been issued to check if an error occured.
   1.454 +//
   1.455 +	{
   1.456 +
   1.457 +	if (!WaitForNotBusy())
   1.458 +		return(KErrTimedOut);
   1.459 +	return(CheckForError());
   1.460 +	}
   1.461 +
   1.462 +TInt DPcCardMediaDriverAta::CheckForError()
   1.463 +//
   1.464 +// Called each time a command has been issued to check if an error occured.
   1.465 +//
   1.466 +	{
   1.467 +
   1.468 +	TUint8 status=AtaRegister8(KAtaStatusRd8);
   1.469 +	if (status&KAtaStatusDrq)
   1.470 +		{
   1.471 +		__KTRACE_CARD_ERROR(KPBUSDRV,Kern::Printf("Ata:CheckForError-DRQ fail"));
   1.472 +		return KErrBadDrq;
   1.473 +		}
   1.474 +	if (status&KAtaStatusDwf)
   1.475 +		{
   1.476 +		__KTRACE_CARD_ERROR(KPBUSDRV,Kern::Printf("Ata:CheckForError-DWF fail"));
   1.477 +		return(KErrWrite);	
   1.478 +		}
   1.479 +	if (status&KAtaStatusErr)
   1.480 +		{
   1.481 +		__KTRACE_CARD_ERROR(KPBUSDRV,Kern::Printf("Ata:CheckForError-ERR fail"));
   1.482 +		return KErrAta;
   1.483 +		}
   1.484 +	return(KErrNone);
   1.485 +	}
   1.486 +
   1.487 +TInt DPcCardMediaDriverAta::ProcessError(TInt anError)
   1.488 +//
   1.489 +// An error has occured - lets get more information
   1.490 +//
   1.491 +	{
   1.492 +
   1.493 +	if (anError==KErrAta&&AtaRegister8(KAtaStatusRd8)&KAtaStatusErr)
   1.494 +		{
   1.495 +		TUint8 basic=AtaRegister8(KAtaErrorRd8);
   1.496 +#if (defined(__EPOC32__) && (defined(_DEBUG) || defined(SHOW_CARD_ERRORS)))
   1.497 +		TUint8 extended=0xFF;		// invalid
   1.498 +		SetAtaRegister8(KAtaCmdRequestSense,KAtaCommandWr8);	// Issue command - request sense
   1.499 +		Kern::NanoWait(400);					// Busy flag not asserted for 400ns
   1.500 +		WaitForNotBusy();
   1.501 +		if (!(AtaRegister8(KAtaStatusRd8)&KAtaStatusErr))
   1.502 +			extended=AtaRegister8(KAtaErrorRd8);
   1.503 +		__KTRACE_CARD_ERROR(KPBUSDRV,Kern::Printf("Ata:ProcessError-Basic:%xH Ext:%xH)",basic,extended));
   1.504 +#endif 
   1.505 +		if (basic&KAtaErrorUnc)
   1.506 +			return(KErrDied);
   1.507 +		else if (basic&(KAtaErrorBbk|KAtaErrorIdnf))
   1.508 +			return(KErrCorrupt);
   1.509 +		else if (basic&KAtaErrorAbort)
   1.510 +			return(KErrCancel);
   1.511 +		else
   1.512 +			return(KErrUnknown);
   1.513 +		}
   1.514 +	else
   1.515 +		return(anError);
   1.516 +	}
   1.517 +
   1.518 +TInt DPcCardMediaDriverAta::EmptySectBufferToTrg(TUint8 *aSrc,TUint aTrgOffset,TInt aLen)
   1.519 +//
   1.520 +// Empty data from sector buffer (at specified offset within buffer) into
   1.521 +// destination descriptor.
   1.522 +//
   1.523 +	{
   1.524 +
   1.525 +	TPtrC8 buf(aSrc,aLen);
   1.526 +	return iCurrentReq->WriteRemote(&buf,aTrgOffset);
   1.527 +	}
   1.528 +
   1.529 +TInt DPcCardMediaDriverAta::LoadSectBufferFromSrc(TInt aLen, TUint8* aBuf)
   1.530 +//
   1.531 +// Load data from source descriptor into sector buffer
   1.532 +// Always called within exec. function.
   1.533 +//
   1.534 +	{
   1.535 +
   1.536 +	TPtr8 buf(aBuf,aLen);
   1.537 +	TInt r=iCurrentReq->ReadRemote(&buf,iCmdInOffset);
   1.538 +	return r;
   1.539 +	}
   1.540 +
   1.541 +TInt DPcCardMediaDriverAta::ReadSectorsCommand(TUint aFirstSector,TUint aBufOffset,TInt aLen)
   1.542 +//
   1.543 +// Start off a read of multiple sectors from the drive (command completed under interrupt/dfc).
   1.544 +//
   1.545 +	{
   1.546 +	__KTRACE_OPT(KPBUSDRV,Kern::Printf(">Ata:ReadSectors F:%x Off:%x L:%x",aFirstSector,aBufOffset,aLen));
   1.547 +
   1.548 +	__ASSERT_DEBUG(aBufOffset<(TUint)KAtaSectorSize,Kern::PanicCurrentThread(_L("ReadSectorsCommand"),0));
   1.549 +	__ASSERT_DEBUG(aLen>0,Kern::PanicCurrentThread(_L("ReadSectorsCommand"),0));
   1.550 +
   1.551 +	// Sector count - allow for not starting on sector boundary by adding buffer offset.  Allow for
   1.552 +	// not ending on sector boundary by adding sectorsize-1. Then divide by sector size.
   1.553 +	TInt tferSectorCount=(aLen+aBufOffset+KAtaSectorSizeMinusOne)>>KAtaSectorShift;
   1.554 +	iNextSector+=tferSectorCount;
   1.555 +	__ASSERT_DEBUG(tferSectorCount<=KMaxSectorsPerRead,Kern::PanicCurrentThread(_L("ReadSectorsCommand"),0));
   1.556 +
   1.557 +	if (!iSocket->CardIsReady())
   1.558 +		return(KErrNotReady);
   1.559 +	AtaRegister8(KAtaStatusRd8);	// Clear any pending interrupt
   1.560 +	iSocket->InterruptEnable(EPccdIntIReq,0); // Enable card interrupt
   1.561 +	TInt err=IssueAtaCommand(KAtaCmdReadSectors,aFirstSector,tferSectorCount);
   1.562 +	if (err!=KErrNone)
   1.563 +		{
   1.564 +		iSocket->InterruptDisable(EPccdIntIReq); // Disable card interrupt
   1.565 +		iCardIreqDfc.Cancel();
   1.566 +		return err;
   1.567 +		}
   1.568 +	iCommandError=KErrNone;
   1.569 +	iNotBusyTickCount=KBusyTimeOut;
   1.570 +	iBusyTimeout.OneShot(NKern::TimerTicks(KNotBusyTestInterval));
   1.571 +	return(KErrNone);
   1.572 +	}
   1.573 +
   1.574 +TInt DPcCardMediaDriverAta::InitiateWriteCommand(TUint aFirstSector,TInt aSectorCount,TUint8 *aSectBuffer)
   1.575 +//
   1.576 +// Start off an asynchronous write to the card. If successful, it leaves with a 
   1.577 +// timeout(ms timer) queued and card interrupts enabled.
   1.578 +//
   1.579 +	{
   1.580 +	__KTRACE_OPT(KPBUSDRV,Kern::Printf(">Ata:InitWrCmd F:%x C:%x",aFirstSector,aSectorCount));
   1.581 +
   1.582 +	__ASSERT_DEBUG((aSectorCount>0 && aSectorCount<=KMaxSectorsPerWrite),Kern::PanicCurrentThread(_L("InitiateWriteCommand"),0));
   1.583 +
   1.584 +	TInt err=IssueAtaCommand(KAtaCmdWriteSectors,aFirstSector,aSectorCount);
   1.585 +	if (err!=KErrNone)
   1.586 +		return(err);
   1.587 +	if (!iSocket->CardIsReady())
   1.588 +		return(KErrNotReady);
   1.589 +	if (!WaitForNotBusy())
   1.590 +		return(ProcessError(KErrTimedOut));
   1.591 +	AtaRegister8(KAtaStatusRd8);	// Clear any pending interrupt
   1.592 +	iSocket->InterruptEnable(EPccdIntIReq,0); // Enable card interrupt
   1.593 +	err=EmptySectBufferToDrive(aSectBuffer);
   1.594 +	if (err!=KErrNone)
   1.595 +		{
   1.596 +		iSocket->InterruptDisable(EPccdIntIReq); // Disable card interrupt
   1.597 +		iCardIreqDfc.Cancel();
   1.598 +		return(ProcessError(err));
   1.599 +		}
   1.600 +	iCommandError=KErrNone;
   1.601 +	iNotBusyTickCount=KBusyTimeOut;
   1.602 +	iBusyTimeout.OneShot(NKern::TimerTicks(KNotBusyTestInterval));
   1.603 +	iNextSector+=aSectorCount;
   1.604 +	return(KErrNone);
   1.605 +	}
   1.606 +
   1.607 +TInt DPcCardMediaDriverAta::SectorBoundaryReadCheck(TUint aStartSector,TUint aStartSectOffset,Int64 anEndPos)
   1.608 +//
   1.609 +// Check for write request which doesn't lie entirely on a sector boundary and perform
   1.610 +// the appropriate sectors reads prior to writing if necessary
   1.611 +//
   1.612 +	{
   1.613 +
   1.614 +	TInt err;
   1.615 +	TUint endSectOffset=((TUint)anEndPos&(~KAtaSectorMask));
   1.616 +	anEndPos-=1;
   1.617 +	anEndPos>>=KAtaSectorShift;
   1.618 +	TUint endSector=(TUint)anEndPos; // Sector number can't exceed 32bits
   1.619 +	TInt sectors=(endSector-aStartSector)+1;
   1.620 +	iLastSectorBufUsed=EFalse;
   1.621 +
   1.622 +	if (aStartSectOffset||endSectOffset)
   1.623 +		{
   1.624 +		// If it requires a read of two consecutive sectors then read them in one go
   1.625 +		if (aStartSectOffset && endSectOffset && sectors==2)
   1.626 +			return(SectorRead(aStartSector,&iSectorBuf[0],2,KAtaCmdReadSectors));
   1.627 +		else 
   1.628 +			{
   1.629 +			// If write starts off a sector boundary or is a single sector write ending 
   1.630 +			// off a sector boundary then read first sector
   1.631 +			if (aStartSectOffset || (endSectOffset && sectors==1))
   1.632 +				{
   1.633 +				if ((err=SectorRead(aStartSector,&iSectorBuf[0]))!=KErrNone)
   1.634 +					return(err);
   1.635 +				}
   1.636 +			// If write doesn't end on a sector boundary then read the last sector
   1.637 +			if (endSectOffset && sectors>1)
   1.638 +				{
   1.639 +				TUint8* p=iSectorBuf;
   1.640 +				if (sectors<=KMaxSectorsPerWrite)
   1.641 +					p+=(sectors-1)<<KAtaSectorShift;
   1.642 +				else
   1.643 +					{
   1.644 +					p=iLastSectorBuf;
   1.645 +					iLastSectorBufUsed=ETrue;
   1.646 +					}
   1.647 +				return(SectorRead(endSector,p));
   1.648 +				}
   1.649 +			}
   1.650 +		}
   1.651 +	return(KErrNone);
   1.652 +	}
   1.653 +
   1.654 +TInt DPcCardMediaDriverAta::SectorRead(TUint aFirstSector,TUint8 *aBuf,TInt aSectorCount,TUint8 aCmd)
   1.655 +//
   1.656 +// Read either 1 or 2 sectors into the sector buffer (synchronously)
   1.657 +//
   1.658 +	{
   1.659 +
   1.660 +	TInt err;
   1.661 +	if ( (err=IssueAtaCommand(aCmd,aFirstSector,aSectorCount))==KErrNone)
   1.662 +		{
   1.663 +		if (
   1.664 +			(err=TransferSectBufferFromDrive(aBuf))!=KErrNone||
   1.665 +			(aSectorCount>1&&(err=TransferSectBufferFromDrive((TAny*)(aBuf+KAtaSectorSize)))!=KErrNone)||
   1.666 +			(err=FinishCommand())!=KErrNone
   1.667 +		   )
   1.668 +			err=ProcessError(err);
   1.669 +		}
   1.670 +	if (!iSocket->CardIsReady())
   1.671 +		err=KErrNotReady; // If media change - return not ready rather than anything else.
   1.672 +	return(err);
   1.673 +	}
   1.674 +
   1.675 +void DPcCardMediaDriverAta::DumpIdentifyDriveInfo()
   1.676 +//
   1.677 +// Debug option to display the drive indentification info.
   1.678 +//
   1.679 +	{
   1.680 +#ifdef _DEBUG
   1.681 +	if (KDebugNum(KPBUSDRV))
   1.682 +		{
   1.683 +		for (TInt i=0;i<128;i+=8)
   1.684 +			{
   1.685 +			Kern::Printf("%02x%02x %02x%02x %02x%02x %02x%02x",iSectorBuf[i],iSectorBuf[i+1],iSectorBuf[i+2],iSectorBuf[i+3],iSectorBuf[i+4],\
   1.686 +						iSectorBuf[i+5],iSectorBuf[i+6],iSectorBuf[i+7]);
   1.687 +			}
   1.688 +		}
   1.689 +#endif 
   1.690 +	}
   1.691 +
   1.692 +TInt DPcCardMediaDriverAta::IdentifyDrive()
   1.693 +//
   1.694 +// Get drive charateristics
   1.695 +//
   1.696 +	{
   1.697 +	__KTRACE_OPT(KPBUSDRV,Kern::Printf(">Ata:IdentifyDrive"));
   1.698 +
   1.699 +	TInt err;
   1.700 +	if ((err=SectorRead(0,&iSectorBuf[0],1,KAtaCmdIdentifyDrive))!=KErrNone)
   1.701 +		return(err);
   1.702 +
   1.703 +	DumpIdentifyDriveInfo();
   1.704 +	TBool lba=EFalse;
   1.705 +	Int64 s=0;
   1.706 +	if (*(TUint16*)(&iSectorBuf[KAtaIdCapabilities])&KAtaIdCapLbaSupported)
   1.707 +		{
   1.708 +		// Card indicates it supports LBA
   1.709 +		// Media size (in sectors) - 2 x halfwords @ KAtaIdTotalSectorsInLba.
   1.710 +		iDriveInfo.iTotalSectorsInLba=*(TInt*)(&iSectorBuf[KAtaIdTotalSectorsInLba]);
   1.711 +		s=iDriveInfo.iTotalSectorsInLba;
   1.712 +		s<<=KAtaSectorShift;
   1.713 +		if (s>0)
   1.714 +			lba=ETrue; // Epson PC card reports LBA supported but LBA size in bytes becomes zero
   1.715 +		} 
   1.716 +
   1.717 +	iDriveInfo.iSupportsLba = lba;
   1.718 +	if (!lba)
   1.719 +		{
   1.720 +		// LBA not supported
   1.721 +		if (*(TUint16*)(&iSectorBuf[KAtaIdTranslationParams])&KAtaIdTrParamsValid)
   1.722 +			{
   1.723 +			// Current translation parameters are valid
   1.724 +			iDriveInfo.iCylinders=*(TUint16*)(&iSectorBuf[KAtaIdCurrentCylinders]);
   1.725 +			iDriveInfo.iHeads=*(TUint16*)(&iSectorBuf[KAtaIdCurrentHeads]);
   1.726 +			iDriveInfo.iSectorsPerTrack=*(TUint16*)(&iSectorBuf[KAtaIdCurrentSectorsPerTrack]);
   1.727 +			}
   1.728 +		else
   1.729 +			{ 
   1.730 +			// Use defaults
   1.731 +			iDriveInfo.iCylinders=*(TUint16*)(&iSectorBuf[KAtaIdDefaultCylinders]);
   1.732 +			iDriveInfo.iHeads=*(TUint16*)(&iSectorBuf[KAtaIdDefaultHeads]);
   1.733 +			iDriveInfo.iSectorsPerTrack=*(TUint16*)(&iSectorBuf[KAtaIdDefaultSectorsPerTrack]);
   1.734 +			} 
   1.735 +		iDriveInfo.iSectorsPerCylinder=(iDriveInfo.iHeads*iDriveInfo.iSectorsPerTrack);
   1.736 +		s=iDriveInfo.iCylinders;
   1.737 +		s*=iDriveInfo.iSectorsPerCylinder;
   1.738 +		s<<=KAtaSectorShift;
   1.739 +		if (iDriveInfo.iSectorsPerCylinder<=0||iDriveInfo.iSectorsPerTrack<=0)
   1.740 +			return(KErrCorrupt);
   1.741 +		}
   1.742 +
   1.743 +	__KTRACE_OPT(KPBUSDRV,Kern::Printf("LBA      : %xH",iDriveInfo.iSupportsLba));
   1.744 +	__KTRACE_OPT(KPBUSDRV,Kern::Printf("Cylinders: %xH",iDriveInfo.iCylinders));
   1.745 +	__KTRACE_OPT(KPBUSDRV,Kern::Printf("Heads    : %xH",iDriveInfo.iHeads));
   1.746 +	__KTRACE_OPT(KPBUSDRV,Kern::Printf("Sectors  : %xH",iDriveInfo.iSectorsPerTrack));
   1.747 +	__KTRACE_OPT(KPBUSDRV,Kern::Printf("<Ata:IdentifyDrive (TS:%lxH)",s));
   1.748 +	SetTotalSizeInBytes(s);
   1.749 +	return(KErrNone);
   1.750 +	}
   1.751 +
   1.752 +TInt DPcCardMediaDriverAta::ConfigAutoPowerDown()
   1.753 +//
   1.754 +// Set auto power down period to something sensible
   1.755 +//
   1.756 +	{
   1.757 +
   1.758 +	TInt err;
   1.759 +	if ( (err=IssueAtaCommand(KAtaCmdIdle,0,200))==KErrNone) // 200x5mS=1S (aFirstSector doesn't matter).
   1.760 +		{
   1.761 +		if ((err=FinishCommand())!=KErrNone)
   1.762 +			err=ProcessError(err);
   1.763 +		}
   1.764 +	__KTRACE_OPT(KPBUSDRV,Kern::Printf("<Ata:ConfigAutoPowerDown-%d",err));
   1.765 +	return(err);
   1.766 +	}
   1.767 +
   1.768 +TInt DPcCardMediaDriverAta::DoOpen()
   1.769 +//
   1.770 +// Open the media driver.
   1.771 +//
   1.772 +	{
   1.773 +
   1.774 +	__KTRACE_OPT(KPBUSDRV,Kern::Printf(">Ata:DoOpen"));
   1.775 +	iCardIreqDfc.SetDfcQ(&iSocket->iDfcQ);
   1.776 +	iTimerDfc.SetDfcQ(&iSocket->iDfcQ);
   1.777 +
   1.778 +	// Card ought to be ready but check we haven't had media change (this causes creation of card functions).
   1.779 +	TInt err=iSocket->CardIsReadyAndVerified();	// this may also fail with OOM or corrupt
   1.780 +	if (err!=KErrNone)
   1.781 +		return err;
   1.782 +
   1.783 +	// Perform CIS validation - get back info. on card functions present. 
   1.784 +	TPccdType pt;
   1.785 +	if (iSocket->VerifyCard(pt)!=KErrNone)
   1.786 +		return(KErrUnknown);
   1.787 +
   1.788 +	__KTRACE_OPT(KPBUSDRV,Kern::Printf("Ata:DoOpen-Check for ATA function, FuncCount=%d",pt.iFuncCount));
   1.789 +
   1.790 +	// Check for ATA fixed disk function.
   1.791 +	TCisReader cisRd; 
   1.792 +	TInt f;
   1.793 +	TBool isAta=EFalse;
   1.794 +	for (f=0;f<pt.iFuncCount;f++)
   1.795 +		{
   1.796 +		if (pt.iFuncType[f]==EFixedDiskCard)
   1.797 +			{
   1.798 +			// Fixed disk function - check its an ATA. 
   1.799 +			TBuf8<KLargeTplBufSize> tpl;
   1.800 +			cisRd.SelectCis(iSocket->iSocketNumber,f);
   1.801 +			// Must start just after FuncId tuple.
   1.802 +			if (cisRd.FindReadTuple(KCisTplFuncId,tpl)!=KErrNone)
   1.803 +				continue;
   1.804 +			while (cisRd.FindReadTuple(KCisTplFunce,tpl)==KErrNone)
   1.805 +				{
   1.806 +				if (tpl[2]==0x01 && tpl[3]==0x01)	// Interface type - ATA
   1.807 +					isAta=ETrue;
   1.808 +				}
   1.809 +			if (isAta)
   1.810 +				break;
   1.811 +			}
   1.812 +		}
   1.813 +	if (!isAta)
   1.814 +		return(KErrUnknown);
   1.815 +	__KTRACE_OPT(KPBUSDRV,Kern::Printf("Ata:DoOpen-Is ATA"));
   1.816 +
   1.817 +	// Determine best card configuration
   1.818 +	cisRd.Restart();
   1.819 +	TPcCardConfig cf;
   1.820 +	TInt opt=KInvalidConfOpt;
   1.821 +	while(cisRd.FindReadConfig(cf)==KErrNone)
   1.822 +		{
   1.823 +		if (
   1.824 +			 cf.IsMachineCompatible(iSocket->iSocketNumber,KPccdCompatNoVccCheck) && // Hitachi card has no 3.3V config entry
   1.825 +#if defined (SELECT_MEMORY_CONFIG)
   1.826 +			 (cf.iValidChunks==1 && __IS_COMMON_MEM(cf.iChnk[0].iMemType) && cf.iChnk[0].iMemLen==0x800)
   1.827 +#elif defined (SELECT_PRIMARY_IO_CONFIG)
   1.828 +			 (cf.iValidChunks==2 && __IS_IO_MEM(cf.iChnk[0].iMemType) && __IS_IO_MEM(cf.iChnk[1].iMemType) && cf.iChnk[0].iMemBaseAddr==0x1F0)
   1.829 +#else
   1.830 +			 // Choose 16 byte -  contiguous i/o option
   1.831 +			 (cf.iValidChunks==1 && __IS_IO_MEM(cf.iChnk[0].iMemType) && cf.iChnk[0].iMemLen==0x10)
   1.832 +#endif
   1.833 +		   ) 
   1.834 +			{
   1.835 +			opt=cf.iConfigOption;
   1.836 +			break;
   1.837 +			}
   1.838 +		}
   1.839 +	if (opt==KInvalidConfOpt)
   1.840 +		return(KErrNotSupported);
   1.841 +	__KTRACE_OPT(KPBUSDRV,Kern::Printf("Ata:DoOpen-ConfigOpt(%d)",opt));
   1.842 +	__KTRACE_OPT(KPBUSDRV,Kern::Printf("Ata:DoOpen-Pulsed Ints-%d",(cf.iInterruptInfo&KPccdIntPulse)));
   1.843 +
   1.844 +	// Now configure the card. First configure it to memory mode. 
   1.845 +	cf.iConfigOption=0;
   1.846 +	err=iSocket->RequestConfig(f,this,cf,0);
   1.847 +	if (err!=KErrNone)
   1.848 +		return(err);
   1.849 +	if (cf.iRegPresent&KConfigAndStatusRegM)
   1.850 +		iSocket->WriteConfigReg(f,KConfigAndStatusReg,0); 
   1.851 +	if (cf.iRegPresent&KSocketAndCopyRegM)
   1.852 +		iSocket->WriteConfigReg(f,KSocketAndCopyReg,0);	// No twin cards
   1.853 +	iSocket->ReleaseConfig(f,this);
   1.854 +
   1.855 +	cf.iConfigOption=(cf.iInterruptInfo&KPccdIntPulse)?opt:(opt|KConfOptLevIReqM);
   1.856 +//	cf.iConfigOption=(opt|KConfOptLevIReqM); // Force level mode interrupts
   1.857 +#if defined (FORCE_8BIT_ACCESSES)
   1.858 +#if defined (SELECT_MEMORY_CONFIG)
   1.859 +	cf.iChnk[0].iMemType=EPccdCommon8Mem;	// Force it to 8bit Common.
   1.860 +#else
   1.861 +	cf.iChnk[0].iMemType=EPccdIo8Mem;		// Force it to 8bit I/O.
   1.862 +#endif
   1.863 +#endif
   1.864 +
   1.865 +	if ((err=iSocket->RequestConfig(f,this,cf,0))!=KErrNone)
   1.866 +		return(err);
   1.867 +
   1.868 +	// Read back the config option register to verify it has been setup
   1.869 +	TUint8 v;
   1.870 +	if ((err=iSocket->ReadConfigReg(f,0,v))!=KErrNone||v!=(TUint8)cf.iConfigOption)
   1.871 +		return KErrBadPccdConfig;
   1.872 +	iCardFuncNum=f;
   1.873 +	__KTRACE_OPT(KPBUSDRV,Kern::Printf("Ata:DoOpen-Configured(%1xH) OK",v));
   1.874 +
   1.875 +	TUint flag=(cf.iActiveSignals&KSigWaitRequired)?KPccdRequestWait:0;
   1.876 +	err=iDriveChunk.Create(iSocket,cf.iChnk[0],cf.iAccessSpeed,flag);
   1.877 +	if (err!=KErrNone)
   1.878 +		return(err);
   1.879 +	iDriveChunk.SetupChunkHw();
   1.880 +	iMemoryType=cf.iChnk[0].iMemType;
   1.881 +	__KTRACE_OPT(KPBUSDRV,Kern::Printf("Ata:DoOpen-Requested Mem OK"));
   1.882 +
   1.883 +	iSocket->InterruptDisable(EPccdIntIReq);
   1.884 +	iCardIntCallBack.iSocket=iSocket;
   1.885 +	iCardIntCallBack.Add();
   1.886 +	SetAtaRegister8(0,KAtaDeviceCtlWr8);	// Enable interrupts
   1.887 +
   1.888 +	SetCurrentConsumption(KIdleCurrentInMilliAmps);
   1.889 +	__KTRACE_OPT(KPBUSDRV,Kern::Printf("<Ata:DoOpen-OK"));
   1.890 +	return(KErrNone);
   1.891 +	}
   1.892 +
   1.893 +TBool DPcCardMediaDriverAta::CardPoweredDown()
   1.894 +//
   1.895 +// Returns EFalse as long as card hasn't received power down (emergency or normal).
   1.896 +//
   1.897 +	{
   1.898 +
   1.899 +	// Emergency power down may result in card being powered down before PC Card
   1.900 +	// Controller status is updated - check for EPD as well as PC Card Contoller.
   1.901 +	return(!Kern::PowerGood() || !iSocket->CardIsReady());
   1.902 +	}
   1.903 +
   1.904 +void DPcCardMediaDriverAta::IncrementSectBufPtr()
   1.905 +//
   1.906 +//
   1.907 +//
   1.908 +	{
   1.909 +
   1.910 +	iSectBufPtr+=KAtaSectorSize;
   1.911 +	if ((iSectBufPtr-&iSectorBuf[0])>=KSectBufSizeInBytes)
   1.912 +		iSectBufPtr=&iSectorBuf[0];
   1.913 +	}
   1.914 +
   1.915 +TInt DPcCardMediaDriverAta::Request(TLocDrvRequest& m)
   1.916 +	{
   1.917 +	__KTRACE_OPT(KLOCDRV,Kern::Printf("Ata:Req %08x id %d",&m,m.Id()));
   1.918 +	TInt r=KErrNotSupported;
   1.919 +	TInt id=m.Id();
   1.920 +	if (id==DLocalDrive::ECaps)
   1.921 +		{
   1.922 +		TLocalDriveCapsV6& c=*(TLocalDriveCapsV6*)m.RemoteDes();
   1.923 +		r=Caps(c);
   1.924 +		c.iSize=m.Drive()->iPartitionLen;
   1.925 +		c.iPartitionType=m.Drive()->iPartitionType;
   1.926 +		return r;
   1.927 +		}
   1.928 +	if (iCurrentReq)
   1.929 +		{
   1.930 +		// a request is already in progress, so hold on to this one
   1.931 +		__KTRACE_OPT(KLOCDRV,Kern::Printf("Ata:Req %08x ret 1",&m));
   1.932 +		return KMediaDriverDeferRequest;
   1.933 +		}
   1.934 +	iCurrentReq=&m;
   1.935 +	switch (id)
   1.936 +		{
   1.937 +		case DLocalDrive::ERead:
   1.938 +			r=DoRead();
   1.939 +			break;
   1.940 +		case DLocalDrive::EWrite:
   1.941 +			r=DoWrite();
   1.942 +			break;
   1.943 +		case DLocalDrive::EFormat:
   1.944 +			r=DoFormat();
   1.945 +			break;
   1.946 +		case DLocalDrive::EEnlarge:
   1.947 +		case DLocalDrive::EReduce:
   1.948 +		default:
   1.949 +			r=KErrNotSupported;
   1.950 +			break;
   1.951 +		}
   1.952 +	__KTRACE_OPT(KLOCDRV,Kern::Printf("Ata:Req %08x cmp %d",&m,r));
   1.953 +	if (r!=KErrNone)
   1.954 +		iCurrentReq=NULL;
   1.955 +	return r;
   1.956 +	}
   1.957 +
   1.958 +void DPcCardMediaDriverAta::NotifyPowerDown()
   1.959 +	{
   1.960 +	__KTRACE_OPT(KPBUSDRV,Kern::Printf(">Ata:NotifyPowerDown"));
   1.961 +	Complete(KErrNotReady);
   1.962 +	Reset();
   1.963 +	}
   1.964 +
   1.965 +void DPcCardMediaDriverAta::NotifyEmergencyPowerDown()
   1.966 +	{
   1.967 +	__KTRACE_OPT(KPBUSDRV,Kern::Printf(">Ata:NotifyEmergencyPowerDown"));
   1.968 +	TInt r=KErrNotReady;
   1.969 +	if (iCritical)
   1.970 +		r=KErrAbort;
   1.971 +	EndInCritical();
   1.972 +	Complete(r);
   1.973 +	Reset();
   1.974 +	}
   1.975 +
   1.976 +void DPcCardMediaDriverAta::TimerDfcFunction(TAny* aPtr)
   1.977 +//
   1.978 +// DFC callback from not-busy timer
   1.979 +//
   1.980 +	{
   1.981 +	DPcCardMediaDriverAta &md=*(DPcCardMediaDriverAta*)aPtr;
   1.982 +	__KTRACE_OPT2(KPBUSDRV,KFAIL,Kern::Printf(">Ata:TimerDfcFunction TC:%d",md.iNotBusyTickCount));
   1.983 +	TInt r=1;
   1.984 +	if (!md.CardPoweredDown())
   1.985 +		{
   1.986 +		md.iDriveChunk.SetupChunkHw();
   1.987 +		TUint8 status=md.AtaRegister8(KAtaStatusRd8); // Clears interrupt
   1.988 +		if (!(status&KAtaStatusBusy))
   1.989 +			{
   1.990 +			// It is not-busy so process it as we would from an interrupt
   1.991 +			__KTRACE_OPT2(KPBUSDRV,KFAIL,Kern::Printf("Card not busy"));
   1.992 +			r=KErrNone;
   1.993 +#ifdef COUNT_TIMEOUTS
   1.994 +			++md.iTimeouts;
   1.995 +			md.iNewTimeOut=ETrue;
   1.996 +			if (md.iIndex<=6)
   1.997 +				{
   1.998 +				md.iInfo[md.iIndex++]=md.iCmdInOffset;
   1.999 +				md.iInfo[md.iIndex++]=md.iCmdEndOffset;
  1.1000 +				}
  1.1001 +#endif
  1.1002 +			}
  1.1003 +		else
  1.1004 +			{
  1.1005 +			// still busy so count tick and restart timer
  1.1006 +			if (--md.iNotBusyTickCount==0)
  1.1007 +				{
  1.1008 +				__KTRACE_OPT2(KPBUSDRV,KFAIL,Kern::Printf("Timed out"));
  1.1009 +				r=KErrTimedOut;		// time out the request
  1.1010 +				}
  1.1011 +			else
  1.1012 +				{
  1.1013 +				__KTRACE_OPT2(KPBUSDRV,KFAIL,Kern::Printf("Restart timer"));
  1.1014 +				md.iBusyTimeout.OneShot(NKern::TimerTicks(KNotBusyTestInterval));
  1.1015 +				}
  1.1016 +			}
  1.1017 +		}
  1.1018 +	else
  1.1019 +		r=KErrNotReady;
  1.1020 +	__KTRACE_OPT2(KPBUSDRV,KFAIL,Kern::Printf("<Ata:TimerDfcFunction r=%d",r));
  1.1021 +	if (r<=0)
  1.1022 +		{
  1.1023 +		// card is not-busy, powered down or timed out
  1.1024 +		md.iSocket->InterruptDisable(EPccdIntIReq); // Disable IREQ in controller
  1.1025 +		md.iCardIreqDfc.Cancel();	// so we don't run this twice
  1.1026 +		md.iCommandError=r;
  1.1027 +		CardIreqDfcFunction(&md);
  1.1028 +		}
  1.1029 +	}
  1.1030 +
  1.1031 +void DPcCardMediaDriverAta::CardIntCallBack(TAny* aMediaDriver, TInt)
  1.1032 +//
  1.1033 +// Card Interrupt callback
  1.1034 +//
  1.1035 +	{
  1.1036 +	__TRACE_TIMING(0x104);
  1.1037 +	DPcCardMediaDriverAta &md=*(DPcCardMediaDriverAta*)aMediaDriver;
  1.1038 +	md.iSocket->InterruptDisable(EPccdIntIReq); // Disable IREQ in controller
  1.1039 +	md.iCardIreqDfc.Add();
  1.1040 +#ifdef COUNT_TIMEOUTS
  1.1041 +	++md.iInts;
  1.1042 +#endif
  1.1043 +	}
  1.1044 +
  1.1045 +void DPcCardMediaDriverAta::CardIreqDfcFunction(TAny* aPtr)
  1.1046 +	{
  1.1047 +
  1.1048 +	DPcCardMediaDriverAta &md=*(DPcCardMediaDriverAta*)aPtr;
  1.1049 +	TInt err=md.iCommandError;
  1.1050 +	TBool queueDfc=md.CardPoweredDown();
  1.1051 +	if (queueDfc)
  1.1052 +		err=KErrNotReady;
  1.1053 +	else if (err!=KErrNone)
  1.1054 +		queueDfc=ETrue;		// timed out
  1.1055 +	else
  1.1056 +		{
  1.1057 +		md.iDriveChunk.SetupChunkHw();
  1.1058 +		TUint8 status=md.AtaRegister8(KAtaStatusRd8); // Clears interrupt
  1.1059 +		if (!(status&KAtaStatusBusy))
  1.1060 +			queueDfc=md.DoCardNotBusy(err);
  1.1061 +		}
  1.1062 +	TBool cmd_done=EFalse;
  1.1063 +	if (queueDfc)
  1.1064 +		{
  1.1065 +		md.iCommandError=err;
  1.1066 +		cmd_done=md.CmdDfc();
  1.1067 +		}
  1.1068 +	if (!queueDfc)
  1.1069 +		{
  1.1070 +		// command still executing so reenable interrupts
  1.1071 +		md.iSocket->InterruptEnable(EPccdIntIReq,0);
  1.1072 +		}
  1.1073 +	if (!cmd_done)
  1.1074 +		{
  1.1075 +		// quickly check if card is already not busy
  1.1076 +		// this handles cards which return data very quickly
  1.1077 +		md.iDriveChunk.SetupChunkHw();
  1.1078 +		TUint8 status=md.AtaRegister8(KAtaStatusRd8); // Clears interrupt
  1.1079 +		if (!(status&KAtaStatusBusy))
  1.1080 +			{
  1.1081 +			md.iSocket->InterruptDisable(EPccdIntIReq);
  1.1082 +			md.iCardIreqDfc.Enque();
  1.1083 +#ifdef COUNT_TIMEOUTS
  1.1084 +			++md.iImmediateNotBusy;
  1.1085 +#endif
  1.1086 +			}
  1.1087 +		else
  1.1088 +			{
  1.1089 +			md.iBusyTimeout.Cancel();
  1.1090 +			md.iTimerDfc.Cancel();
  1.1091 +			md.iBusyTimeout.OneShot(NKern::TimerTicks(KNotBusyTestInterval));
  1.1092 +			}
  1.1093 +		}
  1.1094 +	}
  1.1095 +
  1.1096 +TBool DPcCardMediaDriverAta::DoCardNotBusy(TInt &anErr)
  1.1097 +//
  1.1098 +// Card not busy interrupt - return ETrue when need to queue dfc
  1.1099 +//
  1.1100 +	{
  1.1101 +
  1.1102 +	anErr=KErrNone;
  1.1103 +	if (iCardStatus==ECardWrite || iCardStatus==ECardFormat)
  1.1104 +		{
  1.1105 +		// For write/format commands we only update the out-pointer when the card becomes
  1.1106 +		// not-busy following the point we transfered the block of data to the card.
  1.1107 +		iCmdOutOffset+=(KAtaSectorSize-iSectBufOffset);
  1.1108 +		iSectBufOffset=0;
  1.1109 +		if (iCmdOutOffset<iCmdEndOffset)
  1.1110 +			{
  1.1111 +			TUint8* pB=iSectBufPtr;
  1.1112 +			if (iLastSectorBufUsed && iCmdLength-iCmdOutOffset<=(TUint)KAtaSectorSize)
  1.1113 +				pB=iLastSectorBuf;	// use different buffer for last sector of unaligned write
  1.1114 +			anErr=EmptySectBufferToDrive(pB);
  1.1115 +			if (anErr!=KErrNone)
  1.1116 +				return(ETrue);
  1.1117 +			if (iCardStatus==ECardWrite)
  1.1118 +				iSectBufPtr+=KAtaSectorSize;
  1.1119 +			}
  1.1120 +		else
  1.1121 +			{
  1.1122 +			anErr=CheckForError();
  1.1123 +			return(ETrue);
  1.1124 +			}
  1.1125 +		}
  1.1126 +	if (iCardStatus==ECardRead)
  1.1127 +		{
  1.1128 +		// For read commands we only update the in-pointer here. The out-pointer is
  1.1129 +		// updated by the DFC as data is written to target thread
  1.1130 +
  1.1131 +		// Before we read the data from the card, perform the in-pointer incremeting now. 
  1.1132 +		// If we are about to queue a DFC then let the DFC read from the card. Otherwise,
  1.1133 +		// reading from the card may result in the next sector of data being available
  1.1134 +		// before we're ready for it.
  1.1135 +
  1.1136 +		// If first interrupt after command initiated then allow for sector buffer offset
  1.1137 +		TInt toEOBuf=(iCmdInOffset==0)?(KAtaSectorSize-iSectBufOffset):KAtaSectorSize;
  1.1138 +		TInt remaining=(TInt)(iCmdEndOffset-iCmdInOffset);
  1.1139 +		iCmdInOffset+=Min(remaining,toEOBuf);
  1.1140 +		if ((iSectBufPtr-&iSectorBuf[0])>=KSectBufSizeInBytesMinusOneSector || iCmdInOffset>=iCmdEndOffset)
  1.1141 +			return(ETrue); // Queue a DFC
  1.1142 +		else
  1.1143 +			{
  1.1144 +			anErr=LoadSectBufferFromDrive(iSectBufPtr);
  1.1145 +			if (anErr!=KErrNone)
  1.1146 +				return(ETrue);
  1.1147 +			IncrementSectBufPtr();
  1.1148 +			}
  1.1149 +		}
  1.1150 +	return(EFalse);
  1.1151 +	}
  1.1152 +
  1.1153 +void DPcCardMediaDriverAta::SyncBusyTimerCallBack(TAny* aBusyFlag)
  1.1154 +//
  1.1155 +// Wait for not busy timeout callback
  1.1156 +//
  1.1157 +	{
  1.1158 +
  1.1159 +	*(TBool*)aBusyFlag=ETrue;
  1.1160 +	}
  1.1161 +
  1.1162 +void DPcCardMediaDriverAta::AsyncBusyTimerCallBack(TAny* aMediaDriver)
  1.1163 +//
  1.1164 +// Wait for not busy timeout callback
  1.1165 +//
  1.1166 +	{
  1.1167 +
  1.1168 +	__KTRACE_OPT(KFAIL,Kern::Printf("!,"));
  1.1169 +	DPcCardMediaDriverAta &md=*(DPcCardMediaDriverAta*)aMediaDriver;
  1.1170 +	md.iTimerDfc.Add();
  1.1171 +	}
  1.1172 +
  1.1173 +TBool DPcCardMediaDriverAta::CmdDfc()
  1.1174 +//
  1.1175 +// Dfc to complete an asynchronous command
  1.1176 +//
  1.1177 +	{
  1.1178 +
  1.1179 +	TInt err;
  1.1180 +
  1.1181 +	__KTRACE_OPT(KPBUSDRV,Kern::Printf(">Ata:CmdDfc status %d in %x out %x len %x",iCardStatus,iCmdInOffset,iCmdOutOffset,iCmdLength));
  1.1182 +
  1.1183 +	iBusyTimeout.Cancel();
  1.1184 +	iTimerDfc.Cancel();
  1.1185 +	if (DoCmdDfc(err))	// this requeues timer and reenables interrupts if command still executing
  1.1186 +		{
  1.1187 +		// Command has been completed for one reason or other
  1.1188 +		EndInCritical();
  1.1189 +		if (err!=KErrNone)
  1.1190 +			err=ProcessError(err);
  1.1191 +
  1.1192 +		// If emergency power down on write/format - return abort rather than anything else.
  1.1193 +		if (!Kern::PowerGood() && iCardStatus!=ECardRead)
  1.1194 +			err=KErrAbort;
  1.1195 +		// If media change - return not ready rather than anything else.
  1.1196 +		else if (!iSocket->CardIsReady())
  1.1197 +			err=KErrNotReady;
  1.1198 +		__KTRACE_OPT(KFAIL,Kern::Printf("a%d",err));
  1.1199 +		if (err==KErrNone)
  1.1200 +			{
  1.1201 +			// may need to issue another command here
  1.1202 +			if (iCmdOutOffset<iCmdLength)
  1.1203 +				{
  1.1204 +				if (iCardStatus==ECardRead)
  1.1205 +					{
  1.1206 +					__KTRACE_OPT(KFAIL,Kern::Printf("+R"));
  1.1207 +					__KTRACE_OPT(KPBUSDRV,Kern::Printf(">Ata:NewReadCmd"));
  1.1208 +					iSectBufOffset=0;
  1.1209 +#ifdef COUNT_TIMEOUTS
  1.1210 +					++iChainedReads;
  1.1211 +#endif
  1.1212 +					err=InitiateAsyncRead();
  1.1213 +					if (err==KErrNone)
  1.1214 +						return ETrue;
  1.1215 +					}
  1.1216 +				else
  1.1217 +					{
  1.1218 +					__KTRACE_OPT(KFAIL,Kern::Printf("+W"));
  1.1219 +					__KTRACE_OPT(KPBUSDRV,Kern::Printf(">Ata:NewWriteCmd"));
  1.1220 +#ifdef COUNT_TIMEOUTS
  1.1221 +					++iChainedWrites;
  1.1222 +#endif
  1.1223 +					err=InitiateAsyncWrite();
  1.1224 +					if (err==KErrNone)
  1.1225 +						return ETrue;
  1.1226 +					}
  1.1227 +				}
  1.1228 +			}
  1.1229 +		iCardStatus=ECardIdle;		// Command now complete
  1.1230 +		SetCurrentConsumption(KIdleCurrentInMilliAmps);
  1.1231 +
  1.1232 +#if (defined(_DEBUG) || defined(SHOW_CARD_ERRORS))
  1.1233 +		if (err!=KErrNone&&err!=KErrTooBig)
  1.1234 +			{
  1.1235 +			__KTRACE_CARD_ERROR(KPBUSDRV,Kern::Printf("<DFC(L:%d P:%xH)-%d",iDbgLen,iDbgPos,err));
  1.1236 +			iDbgLastError=err;
  1.1237 +			}
  1.1238 +#endif
  1.1239 +		__TRACE_TIMING(0x109);
  1.1240 +		Complete(err);
  1.1241 +		return ETrue;
  1.1242 +		}
  1.1243 +	return EFalse;
  1.1244 +	}
  1.1245 +
  1.1246 +TBool DPcCardMediaDriverAta::DoCmdDfc(TInt &anErr)
  1.1247 +//
  1.1248 +// Return ETrue when complete
  1.1249 +//
  1.1250 +	{
  1.1251 +
  1.1252 +	if (CardPoweredDown())
  1.1253 +		{
  1.1254 +		anErr=KErrNotReady;
  1.1255 +		return(ETrue);
  1.1256 +		}
  1.1257 +	anErr=iCommandError;
  1.1258 +	if (iCommandError!=KErrNone)
  1.1259 +		return(ETrue);
  1.1260 +
  1.1261 +	if (iCardStatus==ECardWrite||iCardStatus==ECardFormat)
  1.1262 +		return(ETrue);
  1.1263 +	else
  1.1264 +		{
  1.1265 +		// Read command, we postponed loading the last sector
  1.1266 +		__TRACE_TIMING(0x105);
  1.1267 +		if ((anErr=LoadSectBufferFromDrive(iSectBufPtr))!=KErrNone)
  1.1268 +			return(ETrue);
  1.1269 +
  1.1270 +		// In case command still executing, queue another timeout and re-enable interrupts
  1.1271 +		iSocket->InterruptEnable(EPccdIntIReq,0);
  1.1272 +		iNotBusyTickCount=KBusyTimeOut;
  1.1273 +		iBusyTimeout.OneShot(NKern::TimerTicks(KNotBusyTestInterval));
  1.1274 +
  1.1275 +		__TRACE_TIMING(0x106);
  1.1276 +		IncrementSectBufPtr();
  1.1277 +		if ((anErr=EmptySectBufferToTrg(&iSectorBuf[0]+iSectBufOffset,iCmdOutOffset,iCmdInOffset-iCmdOutOffset))!=KErrNone)
  1.1278 +			{
  1.1279 +			iSocket->InterruptDisable(EPccdIntIReq); // Disable IREQ in controller
  1.1280 +			iBusyTimeout.Cancel();
  1.1281 +			iTimerDfc.Cancel();
  1.1282 +			iCardIreqDfc.Cancel();
  1.1283 +			return(ETrue);
  1.1284 +			}
  1.1285 +		__TRACE_TIMING(0x107);
  1.1286 +		iSectBufOffset=0;		// From now on we always start on sector boundary
  1.1287 +		iCmdOutOffset=iCmdInOffset;
  1.1288 +		if (iCmdOutOffset<iCmdEndOffset)
  1.1289 +			return(EFalse);
  1.1290 +		iSocket->InterruptDisable(EPccdIntIReq); // Disable IREQ in controller
  1.1291 +		iBusyTimeout.Cancel();
  1.1292 +		iTimerDfc.Cancel();
  1.1293 +		iCardIreqDfc.Cancel();
  1.1294 +		anErr=FinishCommand();	// This functions involves polling for not busy
  1.1295 +		return(ETrue);
  1.1296 +		}
  1.1297 +	__TRACE_TIMING(0x108);
  1.1298 +	}
  1.1299 +
  1.1300 +DPhysicalDeviceMediaAta::DPhysicalDeviceMediaAta()
  1.1301 +//
  1.1302 +// Constructor
  1.1303 +//
  1.1304 +	{
  1.1305 +	iUnitsMask=0x1;
  1.1306 +	iVersion=TVersion(KMediaDriverInterfaceMajorVersion,KMediaDriverInterfaceMinorVersion,KMediaDriverInterfaceBuildVersion);
  1.1307 +	}
  1.1308 +
  1.1309 +TInt DPhysicalDeviceMediaAta::Install()
  1.1310 +//
  1.1311 +// Install the PC Card ATA Media PDD.
  1.1312 +//
  1.1313 +	{
  1.1314 +	return SetName(&KPddName);
  1.1315 +	}
  1.1316 +
  1.1317 +void DPhysicalDeviceMediaAta::GetCaps(TDes8 &/* aDes */) const
  1.1318 +//
  1.1319 +// Return the media drivers capabilities.
  1.1320 +//
  1.1321 +	{
  1.1322 +	}
  1.1323 +								 
  1.1324 +TInt DPhysicalDeviceMediaAta::Create(DBase*& aChannel, TInt aMediaId, const TDesC8* /*anInfo*/, const TVersion& aVer)
  1.1325 +//
  1.1326 +// Create a PC Card ATA media driver.
  1.1327 +//
  1.1328 +	{
  1.1329 +	if (!Kern::QueryVersionSupported(iVersion,aVer))
  1.1330 +		return KErrNotSupported;
  1.1331 +	DPcCardMediaDriverAta* pD=new DPcCardMediaDriverAta(aMediaId);
  1.1332 +	aChannel=pD;
  1.1333 +	TInt r=KErrNoMemory;
  1.1334 +	if (pD)
  1.1335 +		r=pD->Open();
  1.1336 +	if (r==KErrNone)
  1.1337 +		pD->OpenMediaDriverComplete(KErrNone);
  1.1338 +	return r;
  1.1339 +	}
  1.1340 +
  1.1341 +TInt DPhysicalDeviceMediaAta::Validate(TInt aDeviceType, const TDesC8* anInfo, const TVersion& aVer)
  1.1342 +	{
  1.1343 +	if (!Kern::QueryVersionSupported(iVersion,aVer))
  1.1344 +		return KErrNotSupported;
  1.1345 +	if (aDeviceType!=MEDIA_DEVICE_PCCARD)
  1.1346 +		return KErrNotSupported;
  1.1347 +	return KErrNone;
  1.1348 +	}
  1.1349 +
  1.1350 +TInt DPhysicalDeviceMediaAta::Info(TInt aFunction, TAny*)
  1.1351 +//
  1.1352 +// Return the priority of this media driver
  1.1353 +//
  1.1354 +	{
  1.1355 +	if (aFunction==EPriority)
  1.1356 +		return KAtaDriverPriority;
  1.1357 +	return KErrNotSupported;
  1.1358 +	}
  1.1359 +
  1.1360 +DPcCardMediaDriverAta::DPcCardMediaDriverAta(TInt aMediaId)
  1.1361 +//
  1.1362 +// Constructor.
  1.1363 +//
  1.1364 +	:	DMediaDriver(aMediaId),
  1.1365 +		iCardIntCallBack(CardIntCallBack,this,KPccdIntMaskIReq),
  1.1366 +		iBusyTimeout(AsyncBusyTimerCallBack,this),
  1.1367 +		iCardIreqDfc(CardIreqDfcFunction,this,2),
  1.1368 +		iTimerDfc(TimerDfcFunction,this,2)
  1.1369 +	{
  1.1370 +
  1.1371 +	iMemoryType=EPccdIo8Mem;
  1.1372 +//	iCommandError=KErrNone;
  1.1373 +//	TUint iCmdInOffset=0;
  1.1374 +//	TUint iCmdOutOffset=0;
  1.1375 +//	iCmdEndOffset=0;
  1.1376 +//	iSectBufPtr=NULL;
  1.1377 +//	iSectBufOffset=0;
  1.1378 +	iCardStatus=ECardIdle;
  1.1379 +//	iHiddenSectors=0;
  1.1380 +	iCardFuncNum=-1;
  1.1381 +	}
  1.1382 +
  1.1383 +TInt DPcCardMediaDriverAta::Open()
  1.1384 +//
  1.1385 +// Open the media driver.
  1.1386 +//
  1.1387 +	{
  1.1388 +
  1.1389 +	// Open the driver and get drive characteristics
  1.1390 +	iSocket=((DPcCardSocket*)((DPBusPrimaryMedia*)iPrimaryMedia)->iSocket);
  1.1391 +	__KTRACE_OPT(KPBUSDRV,Kern::Printf(">Ata:Open on socket %d",iSocket->iSocketNumber));
  1.1392 +	TInt r=DoOpen();
  1.1393 +	if (r==KErrNone)
  1.1394 +		r=IdentifyDrive();
  1.1395 +	if (r!=KErrNone)
  1.1396 +		{
  1.1397 +		DoClose();
  1.1398 +		if (!iSocket->CardIsReady())
  1.1399 +			r=KErrNotReady; // If media change - return not ready rather than anything else.
  1.1400 +		}
  1.1401 +	__KTRACE_OPT(KPBUSDRV,Kern::Printf("<Ata:Open-%d",r));
  1.1402 +	return r;
  1.1403 +	}
  1.1404 +
  1.1405 +TInt DPcCardMediaDriverAta::CheckDevice(TBool aCheckPower)
  1.1406 +//
  1.1407 +// Check the device before initiating a command
  1.1408 +//
  1.1409 +	{
  1.1410 +	
  1.1411 +	if (iSocket->CardIsReadyAndVerified()!=KErrNone)
  1.1412 +		return KErrNotReady;
  1.1413 +	if (aCheckPower && Kern::MachinePowerStatus()<ELow)
  1.1414 +		return KErrBadPower;
  1.1415 +	return KErrNone;
  1.1416 +	}
  1.1417 +
  1.1418 +TInt DPcCardMediaDriverAta::DoRead()
  1.1419 +//
  1.1420 +// Read from specified area of media.
  1.1421 +//
  1.1422 +	{
  1.1423 +
  1.1424 +	Int64 aPos=iCurrentReq->Pos();
  1.1425 +	TInt aLength=(TInt)iCurrentReq->Length();
  1.1426 +	TInt err;
  1.1427 +	iCmdOutOffset=0;	// Progress monitor - data delivered to target
  1.1428 +#if (defined(_DEBUG) || defined(SHOW_CARD_ERRORS))
  1.1429 +	iDbgPos=(TUint)aPos;
  1.1430 +	iDbgLen=aLength;
  1.1431 +#endif
  1.1432 +	err=CheckDevice(EFalse);
  1.1433 +	if (err==KErrNone)
  1.1434 +		{
  1.1435 +		iDriveChunk.SetupChunkHw(); // Enable our h/w chunk
  1.1436 +	
  1.1437 +		TUint sectorBufOffset=(TUint)aPos&(~KAtaSectorMask);
  1.1438 +		Int64 firstSector=(aPos>>KAtaSectorShift);
  1.1439 +		iCmdLength=aLength;
  1.1440 +
  1.1441 +		SetCurrentConsumption(KReadCurrentInMilliAmps);
  1.1442 +
  1.1443 +		// Start an asynchronous read
  1.1444 +		iCmdInOffset=0; 					// Data received from card
  1.1445 +		iNextSector=(TUint)firstSector;
  1.1446 +		iSectBufOffset=sectorBufOffset;
  1.1447 +		err=InitiateAsyncRead();
  1.1448 +		if (err==KErrNone)
  1.1449 +			return KErrNone;
  1.1450 +
  1.1451 +		iCardStatus=ECardIdle;
  1.1452 +		SetCurrentConsumption(KIdleCurrentInMilliAmps);
  1.1453 +		if (!iSocket->CardIsReady())
  1.1454 +			err=KErrNotReady; // If media change - return not ready rather than anything else.
  1.1455 +		}
  1.1456 +
  1.1457 +#if (defined(_DEBUG) || defined(SHOW_CARD_ERRORS))
  1.1458 +	__KTRACE_CARD_ERROR(KPBUSDRV,Kern::Printf("<Ata:Read(L:%d P:%xH)-%d",iDbgLen,iDbgPos,err));
  1.1459 +	iDbgLastError=err;
  1.1460 +#endif
  1.1461 +	return err;
  1.1462 +	}
  1.1463 +
  1.1464 +TInt DPcCardMediaDriverAta::InitiateAsyncRead()
  1.1465 +	{
  1.1466 +	// Start an asynchronous read
  1.1467 +	TInt cmdLen=Min(TInt(iCmdLength-iCmdInOffset),TInt(KMaxBytesPerRead-iSectBufOffset)); // Leave it on sector boundary if another read required
  1.1468 +	iCmdEndOffset=iCmdInOffset+cmdLen;	// Marks point when transfer is complete
  1.1469 +	iSectBufPtr=&iSectorBuf[0];
  1.1470 +	iCardStatus=ECardRead;
  1.1471 +	__TRACE_TIMING(0x102);
  1.1472 +	return ReadSectorsCommand(iNextSector,iSectBufOffset,cmdLen);	// Sector number can't exceed 32bits
  1.1473 +	}
  1.1474 +
  1.1475 +TInt DPcCardMediaDriverAta::DoWrite()
  1.1476 +//
  1.1477 +// Write to specified area of media.
  1.1478 +//
  1.1479 +	{
  1.1480 +
  1.1481 +	Int64 aPos=iCurrentReq->Pos();
  1.1482 +	TInt aLength=(TInt)iCurrentReq->Length();
  1.1483 +	TInt err;
  1.1484 +#if (defined(_DEBUG) || defined(SHOW_CARD_ERRORS))
  1.1485 +	iDbgPos=(TUint)aPos;
  1.1486 +	iDbgLen=aLength;
  1.1487 +#endif
  1.1488 +	err=CheckDevice(ETrue);
  1.1489 +	if (err==KErrNone)
  1.1490 +		{
  1.1491 +		iDriveChunk.SetupChunkHw(); // Enable our h/w chunk
  1.1492 +		TUint sectorBufOffset=(TUint)aPos&(~KAtaSectorMask);
  1.1493 +		Int64 firstSector=(aPos>>KAtaSectorShift);
  1.1494 +		iCmdLength=aLength;
  1.1495 +
  1.1496 +		// for unaligned writes, first need to read the first and/or last sector
  1.1497 +		err=SectorBoundaryReadCheck((TUint)firstSector,sectorBufOffset,aPos+iCmdLength);
  1.1498 +		if (err==KErrNone) // Sector number can't exceed 32bits
  1.1499 +			{
  1.1500 +			// Time to actually start the write. First alter the current consumption 
  1.1501 +			// and save the data required to complete the write (in the ISR)
  1.1502 +			SetCurrentConsumption(KWriteCurrentInMilliAmps);
  1.1503 +			iSectBufOffset=sectorBufOffset;
  1.1504 +			iCmdInOffset=0;
  1.1505 +			iCmdOutOffset=0;		// Progress monitor - data delivered to card
  1.1506 +			iNextSector=(TUint)firstSector;
  1.1507 +			iCardStatus=ECardWrite;
  1.1508 +			err=InitiateAsyncWrite();
  1.1509 +			if (err==KErrNone)
  1.1510 +				return KErrNone;
  1.1511 +			SetCurrentConsumption(KIdleCurrentInMilliAmps);
  1.1512 +			}
  1.1513 +		iCardStatus=ECardIdle;
  1.1514 +		if (!Kern::PowerGood())
  1.1515 +			err=KErrAbort; // If emergency power down - return abort rather than anything else.
  1.1516 +		else if (!iSocket->CardIsReady())
  1.1517 +			err=KErrNotReady; // If media change - return not ready rather than anything else.
  1.1518 +		}
  1.1519 +
  1.1520 +#if (defined(_DEBUG) || defined(SHOW_CARD_ERRORS))
  1.1521 +	__KTRACE_CARD_ERROR(KPBUSDRV,Kern::Printf("<Ata:Write(L:%d P:%xH)-%d",iDbgLen,iDbgPos,err));
  1.1522 +	iDbgLastError=err;
  1.1523 +#endif
  1.1524 +	return err;
  1.1525 +	}
  1.1526 +
  1.1527 +TInt DPcCardMediaDriverAta::InitiateAsyncWrite()
  1.1528 +	{
  1.1529 +	iCmdOutOffset=iCmdInOffset;
  1.1530 +	TInt remain=iCmdLength-iCmdInOffset;
  1.1531 +	TInt cmdLen=Min(remain, KMaxBytesPerWrite-iSectBufOffset);
  1.1532 +	TInt sectCount=(cmdLen+iSectBufOffset+KAtaSectorSize-1)>>KAtaSectorShift;
  1.1533 +	iCmdEndOffset=iCmdOutOffset+cmdLen;
  1.1534 +	iSectBufPtr=iSectorBuf;
  1.1535 +	TUint8* pB=iSectorBuf;
  1.1536 +	TInt r=KErrNone;
  1.1537 +	if (iCardStatus==ECardWrite)
  1.1538 +		{
  1.1539 +		if (iLastSectorBufUsed && cmdLen==remain)
  1.1540 +			{
  1.1541 +			// load data for sectors other than last into sector buffer
  1.1542 +			TInt lengthExcludingLastSector=cmdLen &~ (KAtaSectorSize-1);
  1.1543 +			if (lengthExcludingLastSector==cmdLen)
  1.1544 +				lengthExcludingLastSector-=KAtaSectorSize;
  1.1545 +			if (lengthExcludingLastSector)
  1.1546 +				{
  1.1547 +				r=LoadSectBufferFromSrc(lengthExcludingLastSector,iSectorBuf+iSectBufOffset);
  1.1548 +				if (r!=KErrNone)
  1.1549 +					return r;
  1.1550 +				iCmdInOffset+=lengthExcludingLastSector;	// make sure we get right data for last sector
  1.1551 +				}
  1.1552 +			else
  1.1553 +				pB=iLastSectorBuf;
  1.1554 +			// load last sector data into last sector buffer
  1.1555 +			r=LoadSectBufferFromSrc(cmdLen-lengthExcludingLastSector,iLastSectorBuf);
  1.1556 +			if (r!=KErrNone)
  1.1557 +				return r;
  1.1558 +			iCmdInOffset+=(cmdLen-lengthExcludingLastSector);
  1.1559 +			}
  1.1560 +		else
  1.1561 +			{
  1.1562 +			// Load the the data from source in one go
  1.1563 +			r=LoadSectBufferFromSrc(cmdLen,iSectorBuf+iSectBufOffset);
  1.1564 +			if (r!=KErrNone)
  1.1565 +				return r;
  1.1566 +			iCmdInOffset+=cmdLen;
  1.1567 +			}
  1.1568 +		}
  1.1569 +	else
  1.1570 +		iCmdInOffset+=cmdLen;	// format command
  1.1571 +	r=InCritical();		// this returns KErrNotReady if we are about to do postponed media change or power down
  1.1572 +	if (r==KErrNone)
  1.1573 +		{
  1.1574 +		r=InitiateWriteCommand(iNextSector,sectCount,pB);
  1.1575 +		__KTRACE_OPT(KPBUSDRV,Kern::Printf("InitWrCmd ret %d",r));
  1.1576 +		if (iCardStatus==ECardWrite)
  1.1577 +			iSectBufPtr+=KAtaSectorSize;
  1.1578 +		}
  1.1579 +	if (r!=KErrNone)
  1.1580 +		{
  1.1581 +		if (!Kern::PowerGood())
  1.1582 +			r=KErrAbort; // If emergency power down - return abort rather than anything else.
  1.1583 +		else if (!iSocket->CardIsReady())
  1.1584 +			r=KErrNotReady; // If media change - return not ready rather than anything else.
  1.1585 +		EndInCritical();
  1.1586 +		}
  1.1587 +	return r;
  1.1588 +	}
  1.1589 +
  1.1590 +TInt DPcCardMediaDriverAta::DoFormat()
  1.1591 +//
  1.1592 +// Format the specified area of the media. 
  1.1593 +//
  1.1594 +	{
  1.1595 +	
  1.1596 +	Int64 aPos=iCurrentReq->Pos();
  1.1597 +	TInt aLength=(TInt)iCurrentReq->Length();
  1.1598 +	TInt err;
  1.1599 +#if (defined(_DEBUG) || defined(SHOW_CARD_ERRORS))
  1.1600 +	iDbgPos=(TUint)aPos;
  1.1601 +	iDbgLen=aLength;
  1.1602 +#endif
  1.1603 +	err=CheckDevice(ETrue);
  1.1604 +	if (err==KErrNone)
  1.1605 +		{
  1.1606 +		iDriveChunk.SetupChunkHw(); // Enable our h/w chunk
  1.1607 +		memset(iSectorBuf,0xff,KAtaSectorSize);
  1.1608 +		Int64 firstSector=(aPos>>KAtaSectorShift);
  1.1609 +		TInt sectCount=(aLength+KAtaSectorSizeMinusOne)>>KAtaSectorShift;
  1.1610 +		iCmdLength=(sectCount<<KAtaSectorShift);
  1.1611 +		sectCount=Min(KMaxSectorsPerFormat,(aLength+KAtaSectorSizeMinusOne)>>KAtaSectorShift);
  1.1612 +		SetCurrentConsumption(KWriteCurrentInMilliAmps);
  1.1613 +
  1.1614 +		iLastSectorBufUsed=EFalse;
  1.1615 +		iCmdInOffset=0;
  1.1616 +		iCmdOutOffset=0;		// Progress monitor - data delivered to card
  1.1617 +		iSectBufOffset=0;
  1.1618 +		iSectBufPtr=&iSectorBuf[0];
  1.1619 +		iNextSector=(TUint)firstSector;
  1.1620 +		iCardStatus=ECardFormat;
  1.1621 +		err=InitiateAsyncWrite();
  1.1622 +		if (err==KErrNone)
  1.1623 +			return KErrNone;
  1.1624 +
  1.1625 +		iCardStatus=ECardIdle;
  1.1626 +		SetCurrentConsumption(KIdleCurrentInMilliAmps);
  1.1627 +
  1.1628 +		if (!Kern::PowerGood())
  1.1629 +			err=KErrAbort; // If emergency power down - return abort rather than anything else.
  1.1630 +		else if (!iSocket->CardIsReady())
  1.1631 +			err=KErrNotReady; // If media change - return not ready rather than anything else.
  1.1632 +		}
  1.1633 +
  1.1634 +#if (defined(_DEBUG) || defined(SHOW_CARD_ERRORS))
  1.1635 +	__KTRACE_CARD_ERROR(KPBUSDRV,Kern::Printf("<Ata:Format(L:%d P:%xH)-%d",iDbgLen,iDbgPos,err));
  1.1636 +	iDbgLastError=err;
  1.1637 +#endif
  1.1638 +	return err;
  1.1639 +	}
  1.1640 +
  1.1641 +void DPcCardMediaDriverAta::Close()
  1.1642 +//
  1.1643 +// Close the media driver - also called on media change
  1.1644 +//
  1.1645 +	{
  1.1646 +
  1.1647 +	__KTRACE_OPT(KPBUSDRV,Kern::Printf(">Ata:Close"));
  1.1648 +	EndInCritical();
  1.1649 +	Complete(KErrNotReady);
  1.1650 +	DoClose();
  1.1651 +	DMediaDriver::Close();
  1.1652 +	}
  1.1653 +
  1.1654 +void DPcCardMediaDriverAta::DoClose()
  1.1655 +//
  1.1656 +// Close the media driver
  1.1657 +//
  1.1658 +	{
  1.1659 +
  1.1660 +	__KTRACE_OPT(KPBUSDRV,Kern::Printf(">Ata:DoClose"));
  1.1661 +	iCardIntCallBack.Remove();
  1.1662 +	iDriveChunk.Close();
  1.1663 +	if (iCardFuncNum>=0)
  1.1664 +		{
  1.1665 +		iSocket->ReleaseConfig(iCardFuncNum,this);
  1.1666 +		iCardFuncNum=-1;
  1.1667 +		}
  1.1668 +	Reset();
  1.1669 +	__KTRACE_CARD_ERROR(KPBUSDRV,Kern::Printf("<Ata:DoClose(%d)",iDbgLastError));
  1.1670 +	}
  1.1671 +
  1.1672 +void DPcCardMediaDriverAta::Reset()
  1.1673 +	{
  1.1674 +	__KTRACE_OPT(KPBUSDRV,Kern::Printf(">Ata:Reset"));
  1.1675 +	iBusyTimeout.Cancel();			// In case its currently queued
  1.1676 +	iCardIreqDfc.Cancel();			// In case its currently queued
  1.1677 +	iTimerDfc.Cancel();
  1.1678 +	iCardStatus=ECardIdle;
  1.1679 +	SetCurrentConsumption(0);
  1.1680 +	}
  1.1681 +
  1.1682 +#ifdef KLOCDRV
  1.1683 +void DebugDump(const TMBRPartitionEntry& a)
  1.1684 +	{
  1.1685 +	Kern::Printf("BootInd =%02x StartHead=%02x StartSect=%02x StartCyl=%02x",
  1.1686 +			a.iX86BootIndicator, a.iStartHead, a.iStartSector, a.iStartCylinder);
  1.1687 +	Kern::Printf("PartType=%02x EndHead  =%02x EndSect  =%02x EndCyl  =%02x",
  1.1688 +			a.iPartitionType, a.iEndHead, a.iEndSector, a.iEndCylinder);
  1.1689 +	Kern::Printf("FirstSect=%08x NumSectors=%08x", a.iFirstSector, a.iNumSectors);
  1.1690 +	}
  1.1691 +
  1.1692 +void DebugDump(const TPartitionInfo& a)
  1.1693 +	{
  1.1694 +	Kern::Printf("PartitionInfo: (C:%d)",a.iPartitionCount);
  1.1695 +	TInt i;
  1.1696 +	for (i=0; i<KMaxPartitionEntries; ++i)
  1.1697 +		{
  1.1698 +		const TPartitionEntry& e=a.iEntry[i];
  1.1699 +		Kern::Printf("   Partition %d: B=%lxH L=%lxH I=%04x T=%04x", i, e.iPartitionBaseAddr,
  1.1700 +						e.iPartitionLen, e.iBootIndicator, e.iPartitionType );
  1.1701 +		}
  1.1702 +	}
  1.1703 +#endif
  1.1704 +
  1.1705 +void SetPartitionEntry(TPartitionEntry* aDest, const TMBRPartitionEntry* aSrc)
  1.1706 +//
  1.1707 +// Set the partition entry details
  1.1708 +//
  1.1709 +	{
  1.1710 +
  1.1711 +	aDest->iPartitionBaseAddr=aSrc->iFirstSector;
  1.1712 +	aDest->iPartitionBaseAddr<<=KAtaSectorShift;
  1.1713 +	aDest->iPartitionLen=aSrc->iNumSectors;
  1.1714 +	aDest->iPartitionLen<<=KAtaSectorShift;
  1.1715 +	aDest->iBootIndicator=aSrc->iX86BootIndicator;
  1.1716 +	aDest->iPartitionType=aSrc->iPartitionType;
  1.1717 +	}
  1.1718 +
  1.1719 +TInt DPcCardMediaDriverAta::PartitionInfo(TPartitionInfo& anInfo)
  1.1720 +//
  1.1721 +// Return partition information on the media.
  1.1722 +//
  1.1723 +	{
  1.1724 +
  1.1725 +	__KTRACE_OPT(KPBUSDRV,Kern::Printf(">Ata:PartitionInfo"));
  1.1726 +	if (iSocket->CardIsReadyAndVerified()!=KErrNone)
  1.1727 +		return(KErrNotReady);
  1.1728 +	TInt partitionCount=anInfo.iPartitionCount=0;
  1.1729 +
  1.1730 +	// Read the first sector and check for a Master Boot Record
  1.1731 +	TInt err;
  1.1732 +	if ((err=SectorRead(0,&iSectorBuf[0]))!=KErrNone)
  1.1733 +		return(err);
  1.1734 +	if (*(TUint16*)(&iSectorBuf[KMBRSignatureOffset])!=KMBRSignature)
  1.1735 +		return(KErrCorrupt);
  1.1736 +
  1.1737 +	// Move the partition entries to a 4 byte boundary
  1.1738 +	memmove(&iSectorBuf[0],&iSectorBuf[KMBRFirstPartitionOffset],(sizeof(TMBRPartitionEntry)*KMBRMaxPrimaryPartitions));
  1.1739 +
  1.1740 +	// Search for a x86 default boot partition - let this be the first
  1.1741 +	TMBRPartitionEntry *pe=(TMBRPartitionEntry*)(&iSectorBuf[0]);
  1.1742 +	TInt i;
  1.1743 +	TInt defaultPartitionNumber=-1;
  1.1744 +	for (i=0;i<KMBRMaxPrimaryPartitions;i++,pe++)
  1.1745 +		{
  1.1746 +		if (pe->IsDefaultBootPartition())
  1.1747 +			{
  1.1748 +			SetPartitionEntry(anInfo.iEntry, pe);
  1.1749 +			defaultPartitionNumber=i;
  1.1750 +			iHiddenSectors=pe->iFirstSector;
  1.1751 +			partitionCount++;
  1.1752 +			break;
  1.1753 +			}
  1.1754 +		}
  1.1755 +
  1.1756 +	// Now add any other partitions
  1.1757 +	pe=(TMBRPartitionEntry*)(&iSectorBuf[0]);	// Reset it
  1.1758 +	for (i=0;i<KMBRMaxPrimaryPartitions;i++,pe++)
  1.1759 +		{
  1.1760 +		__KTRACE_OPT(KLOCDRV, Kern::Printf("Partition %d:",i));
  1.1761 +		__KTRACE_OPT(KLOCDRV, DebugDump(*pe));
  1.1762 +		if (defaultPartitionNumber==i)
  1.1763 +			continue;	// Already sorted
  1.1764 +		if (pe->IsValidDosPartition() || pe->IsValidFAT32Partition())
  1.1765 +			{
  1.1766 +			SetPartitionEntry(anInfo.iEntry+partitionCount, pe);
  1.1767 +			partitionCount++;
  1.1768 +			}
  1.1769 +		}
  1.1770 +	anInfo.iPartitionCount=partitionCount;
  1.1771 +	anInfo.iMediaSizeInBytes=TotalSizeInBytes();
  1.1772 +
  1.1773 +	__KTRACE_OPT(KLOCDRV, DebugDump(anInfo));
  1.1774 +
  1.1775 +	PartitionInfoComplete(KErrNone);
  1.1776 +	return KErrNone;
  1.1777 +	}
  1.1778 +
  1.1779 +TInt DPcCardMediaDriverAta::Caps(TLocalDriveCapsV6& aInfo)
  1.1780 +//
  1.1781 +// Return the capabilities of the media
  1.1782 +//
  1.1783 +	{
  1.1784 +	aInfo.iType=EMediaHardDisk;
  1.1785 +	aInfo.iConnectionBusType=EConnectionBusInternal;
  1.1786 +	aInfo.iDriveAtt=KDriveAttLocal|KDriveAttRemovable;
  1.1787 +	aInfo.iMediaAtt=KMediaAttFormattable;
  1.1788 +	aInfo.iFileSystemId=KDriveFileSysFAT;
  1.1789 +	aInfo.iHiddenSectors=iHiddenSectors;
  1.1790 +	aInfo.iBlockSize=KAtaSectorSize;
  1.1791 +	return KErrCompletion;	// synchronous completion
  1.1792 +	}
  1.1793 +
  1.1794 +DECLARE_STANDARD_PDD()
  1.1795 +	{
  1.1796 +	return new DPhysicalDeviceMediaAta;
  1.1797 +	}
  1.1798 +