os/kernelhwsrv/kernel/eka/drivers/medata/pccd_ata.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     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.iConnectionBusType=EConnectionBusInternal;
  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