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