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