os/kernelhwsrv/userlibandfileserver/fileserver/smassstorage/inc/rwdrivethread.h
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 2007-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 // Thread for reading and writing to a drive.
    15 // 
    16 //
    17 
    18 /**
    19  @file
    20  @internalTechnology
    21 */
    22 
    23 #ifndef __RWDRIVETHREAD_H__
    24 #define __RWDRIVETHREAD_H__
    25 
    26 #ifdef MSDC_MULTITHREADED
    27 
    28 typedef void (*ProcessWriteCompleteFunc)(TUint8* aAddress, TAny* aPtr);
    29 
    30 
    31 /**
    32 Class contains buffer for data with associated drive offset and length in bytes.
    33 */
    34 
    35 class TBlockDesc
    36 {
    37 public:
    38 
    39 	TBlockDesc();
    40 	void SetPtr(TPtr8& aDes);
    41 
    42 	TPtr8 GetReadBuffer();
    43 	TPtr8 GetReadBuffer(TUint aLength, const TInt64& aOffset);
    44 
    45 public:
    46 	TInt64 iByteOffset;
    47 	TUint iLength;
    48 	TPtr8 iBuf;
    49 };
    50 
    51 
    52 /**
    53 Class contains two buffers. Whilst one buffer is being read the
    54 other buffer can be written to. The buffers should be accessed 
    55 by the buffer pointers iDescReadPtr and iDescWritePtr.
    56 */
    57 
    58 class TBlockDescBuffer
    59 {
    60 public:
    61 	TBlockDescBuffer();
    62 
    63 	void SwapDesc();
    64 	TInt MaxLength() const {return iDesc2.iBuf.MaxLength();}
    65 	TInt GetBufferNumber(const TPtr8* aBufferPtr) const;
    66 	void SetUpReadBuf(TPtr8& aDes1, TPtr8& aDes2);
    67 
    68 public:
    69 	/** Points to block descriptor containing buffer to read from */
    70 	TBlockDesc* iDescReadPtr;
    71 	/** Points to block descriptor containing buffer to write to */
    72 	TBlockDesc* iDescWritePtr;
    73 	
    74 private:
    75 	/** Block descriptor for read/write operations */
    76 	TBlockDesc iDesc1;
    77 	/** Block descriptor for read/write operations */
    78 	TBlockDesc iDesc2;
    79 };
    80 
    81 
    82 /**
    83 Provides the common thread context used by CReadDriveThread and CWriteDriveThread 
    84 classes.
    85 */
    86 class CThreadContext : public CBase
    87 {
    88 public:
    89 	static CThreadContext* NewL(const TDesC& aName,
    90 								TThreadFunction aThreadFunction,
    91 								TAny* aOwner);
    92 	~CThreadContext();
    93 
    94 private:
    95 	CThreadContext();
    96 	void ConstructL(const TDesC& aName, TThreadFunction aThreadFunction, TAny* aOwner);
    97 
    98 
    99 public:
   100 	void Resume() {iThread.Resume();}
   101 
   102 	TInt MaxBufferLength() const {return iBuffer.MaxLength();} 
   103 	TPtr8 GetReadBuffer();
   104 	TPtr8 GetReadBuffer(TInt aLength);
   105 
   106 	TPtrC8 WriteBuf();
   107 
   108 public:
   109 	/** Used to tell thread which drive to use */
   110 	CMassStorageDrive* iDrive;
   111 	/** Used by the thread to return error code */
   112 	TInt iError;
   113 	/** CS to regulate read/write buffer access */
   114 	RCriticalSection iCritSect;
   115 	
   116 	/** buffer for reading and writing */
   117 	TBlockDescBuffer iBuffer;
   118 
   119 public:
   120 	RThread iThread;
   121 };
   122 
   123 
   124 /**
   125 Separate disk writer thread, used to implement OUT transfer double-buffering.
   126 */
   127 class CWriteDriveThread : public CBase
   128 	{
   129 public:
   130 	static CWriteDriveThread* NewL();
   131 	~CWriteDriveThread();
   132 
   133 private:
   134 	CWriteDriveThread();
   135 	void ConstructL();
   136 
   137 public:
   138 	TBlockDesc* GetReadDesc();
   139 
   140 	TInt WriteDriveData(CMassStorageDrive* aDrive, const TInt64& aOffset, TPtrC8& aDes, ProcessWriteCompleteFunc aFunc, TAny* aPtr);
   141 
   142 	TUint WriteBufferLength() const {return iThreadContext->iBuffer.iDescWritePtr->iBuf.Length();}
   143 	TUint ReadBufferLength() const {return iThreadContext->iBuffer.iDescReadPtr->iBuf.Length();}
   144 
   145 	TInt DeferredError() const {return iThreadContext->iError;}
   146 	void ClearDeferredError() {iThreadContext->iError = KErrNone;}
   147 	void WaitForWriteEmpty();
   148 
   149 	TBool IsRecentlyWritten(TInt64 aOffset, TInt aLength);
   150 	inline void SetCommandWrite10(TBool aIsWriteCommand) {iIsCommandWrite10 = aIsWriteCommand;};
   151 
   152 private:
   153 	static TInt ThreadFunction(TAny* aSelf);
   154 	TInt WriteToDrive();
   155 
   156 public:
   157 	/** Thread context */
   158 	CThreadContext* iThreadContext;
   159 
   160 	TInt iWriteCounter;
   161 private:
   162 	/** Semaphore for reading USB */
   163 	RSemaphore iProducerSem;
   164 	/** Semaphore for writing to drive */
   165 	RSemaphore iConsumerSem;
   166 	/* Call back to tell transport that 'transfer' was written and the corresponding buffer can be overwriiten (mainly for SC LDD) */
   167 	ProcessWriteCompleteFunc iCallback;
   168 	TAny* iCallbackParameter;
   169 	/* Flag set to true if the command is Write10. Used in Read10 to ignore pre-read if the previous command was Write10 */
   170 	TBool iIsCommandWrite10;
   171 	};
   172 
   173 
   174 /**
   175 Separate disk reader thread, used to implement IN transfer double-buffering.
   176 */
   177 class CReadDriveThread : public CBase
   178 	{
   179 public:
   180 	static CReadDriveThread* NewL();
   181 	~CReadDriveThread();
   182 
   183 private:
   184 	CReadDriveThread();
   185 	void ConstructL();
   186 
   187 public:
   188 	TBool ReadDriveData(CMassStorageDrive* aDrive, const TInt64& aOffset, TUint32 aLength, TBool aIgnoreCache);
   189 	void DiscardRead();
   190 
   191 private:
   192 	static TInt ThreadFunction(TAny* aSelf);
   193 	TInt ReadFromDrive();
   194 
   195 public:
   196 	/** Thread context */
   197 	CThreadContext* iThreadContext;
   198 	TBool iCompleted;
   199 
   200 private:
   201 	TBool iThreadRunning;
   202 	};
   203 
   204 
   205 //-----------------------------------------------
   206 
   207 /**
   208 Swap the buffer which the read and write buffer pointers are pointing to.
   209 */
   210 inline void TBlockDescBuffer::SwapDesc()
   211 {
   212 	TBlockDesc* const tmp = iDescReadPtr;
   213 	iDescReadPtr = iDescWritePtr;
   214 	iDescWritePtr = tmp;
   215 }
   216 
   217 inline TPtr8 TBlockDesc::GetReadBuffer()
   218 {
   219 	return iBuf.LeftTPtr(iBuf.Length());
   220 }
   221 
   222 
   223 inline TPtr8 TBlockDesc::GetReadBuffer(TUint aLength, const TInt64& aOffset)
   224 {
   225 	iByteOffset = aOffset;
   226 	iLength = aLength;
   227 	iBuf.SetLength(aLength);
   228 	
   229 	return GetReadBuffer();
   230 }
   231 
   232 //-----------------------------------------------
   233 
   234 /**
   235 Returns the id of the buffer
   236 
   237 @param bufferPtr pointer to the buffer.
   238 @return  returns the buffer ID or -1 if the buffer is not found.
   239 */
   240 inline TInt TBlockDescBuffer::GetBufferNumber(const TPtr8* aBufferPtr) const
   241 {
   242 	TInt no = -1;
   243 	if (aBufferPtr == &iDesc1.iBuf)
   244 		no = 1;
   245 	else if (aBufferPtr == &iDesc2.iBuf)
   246 		no = 2;
   247 	return no;
   248 }
   249 
   250 
   251 //-----------------------------------------------
   252 
   253 inline TPtr8 CThreadContext::GetReadBuffer()
   254 {
   255 	TInt len = iBuffer.iDescReadPtr->iBuf.Length();
   256 	return iBuffer.iDescReadPtr->iBuf.LeftTPtr(len);
   257 }
   258 
   259 
   260 inline TPtr8 CThreadContext::GetReadBuffer(TInt aLength)
   261 {
   262 	iBuffer.iDescReadPtr->iBuf.SetLength(aLength);
   263 	return GetReadBuffer();
   264 }
   265 
   266 
   267 inline TPtrC8 CThreadContext::WriteBuf()
   268 {
   269 	return iBuffer.iDescWritePtr->iBuf;
   270 }
   271 
   272 //-----------------------------------------------
   273 
   274 inline TBlockDesc* CWriteDriveThread::GetReadDesc()
   275 {
   276 	return iThreadContext->iBuffer.iDescReadPtr;
   277 }
   278 
   279 //-----------------------------------------------
   280 
   281 #endif //  MSDC_MULTITHREADED
   282 
   283 #endif // __RWDRIVETHREAD_H__