userlibandfileserver/fileserver/smassstorage/inc/rwdrivethread.h
changeset 0 a41df078684a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/userlibandfileserver/fileserver/smassstorage/inc/rwdrivethread.h	Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,283 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Thread for reading and writing to a drive.
+// 
+//
+
+/**
+ @file
+ @internalTechnology
+*/
+
+#ifndef __RWDRIVETHREAD_H__
+#define __RWDRIVETHREAD_H__
+
+#ifdef MSDC_MULTITHREADED
+
+typedef void (*ProcessWriteCompleteFunc)(TUint8* aAddress, TAny* aPtr);
+
+
+/**
+Class contains buffer for data with associated drive offset and length in bytes.
+*/
+
+class TBlockDesc
+{
+public:
+
+	TBlockDesc();
+	void SetPtr(TPtr8& aDes);
+
+	TPtr8 GetReadBuffer();
+	TPtr8 GetReadBuffer(TUint aLength, const TInt64& aOffset);
+
+public:
+	TInt64 iByteOffset;
+	TUint iLength;
+	TPtr8 iBuf;
+};
+
+
+/**
+Class contains two buffers. Whilst one buffer is being read the
+other buffer can be written to. The buffers should be accessed 
+by the buffer pointers iDescReadPtr and iDescWritePtr.
+*/
+
+class TBlockDescBuffer
+{
+public:
+	TBlockDescBuffer();
+
+	void SwapDesc();
+	TInt MaxLength() const {return iDesc2.iBuf.MaxLength();}
+	TInt GetBufferNumber(const TPtr8* aBufferPtr) const;
+	void SetUpReadBuf(TPtr8& aDes1, TPtr8& aDes2);
+
+public:
+	/** Points to block descriptor containing buffer to read from */
+	TBlockDesc* iDescReadPtr;
+	/** Points to block descriptor containing buffer to write to */
+	TBlockDesc* iDescWritePtr;
+	
+private:
+	/** Block descriptor for read/write operations */
+	TBlockDesc iDesc1;
+	/** Block descriptor for read/write operations */
+	TBlockDesc iDesc2;
+};
+
+
+/**
+Provides the common thread context used by CReadDriveThread and CWriteDriveThread 
+classes.
+*/
+class CThreadContext : public CBase
+{
+public:
+	static CThreadContext* NewL(const TDesC& aName,
+								TThreadFunction aThreadFunction,
+								TAny* aOwner);
+	~CThreadContext();
+
+private:
+	CThreadContext();
+	void ConstructL(const TDesC& aName, TThreadFunction aThreadFunction, TAny* aOwner);
+
+
+public:
+	void Resume() {iThread.Resume();}
+
+	TInt MaxBufferLength() const {return iBuffer.MaxLength();} 
+	TPtr8 GetReadBuffer();
+	TPtr8 GetReadBuffer(TInt aLength);
+
+	TPtrC8 WriteBuf();
+
+public:
+	/** Used to tell thread which drive to use */
+	CMassStorageDrive* iDrive;
+	/** Used by the thread to return error code */
+	TInt iError;
+	/** CS to regulate read/write buffer access */
+	RCriticalSection iCritSect;
+	
+	/** buffer for reading and writing */
+	TBlockDescBuffer iBuffer;
+
+public:
+	RThread iThread;
+};
+
+
+/**
+Separate disk writer thread, used to implement OUT transfer double-buffering.
+*/
+class CWriteDriveThread : public CBase
+	{
+public:
+	static CWriteDriveThread* NewL();
+	~CWriteDriveThread();
+
+private:
+	CWriteDriveThread();
+	void ConstructL();
+
+public:
+	TBlockDesc* GetReadDesc();
+
+	TInt WriteDriveData(CMassStorageDrive* aDrive, const TInt64& aOffset, TPtrC8& aDes, ProcessWriteCompleteFunc aFunc, TAny* aPtr);
+
+	TUint WriteBufferLength() const {return iThreadContext->iBuffer.iDescWritePtr->iBuf.Length();}
+	TUint ReadBufferLength() const {return iThreadContext->iBuffer.iDescReadPtr->iBuf.Length();}
+
+	TInt DeferredError() const {return iThreadContext->iError;}
+	void ClearDeferredError() {iThreadContext->iError = KErrNone;}
+	void WaitForWriteEmpty();
+
+	TBool IsRecentlyWritten(TInt64 aOffset, TInt aLength);
+	inline void SetCommandWrite10(TBool aIsWriteCommand) {iIsCommandWrite10 = aIsWriteCommand;};
+
+private:
+	static TInt ThreadFunction(TAny* aSelf);
+	TInt WriteToDrive();
+
+public:
+	/** Thread context */
+	CThreadContext* iThreadContext;
+
+	TInt iWriteCounter;
+private:
+	/** Semaphore for reading USB */
+	RSemaphore iProducerSem;
+	/** Semaphore for writing to drive */
+	RSemaphore iConsumerSem;
+	/* Call back to tell transport that 'transfer' was written and the corresponding buffer can be overwriiten (mainly for SC LDD) */
+	ProcessWriteCompleteFunc iCallback;
+	TAny* iCallbackParameter;
+	/* Flag set to true if the command is Write10. Used in Read10 to ignore pre-read if the previous command was Write10 */
+	TBool iIsCommandWrite10;
+	};
+
+
+/**
+Separate disk reader thread, used to implement IN transfer double-buffering.
+*/
+class CReadDriveThread : public CBase
+	{
+public:
+	static CReadDriveThread* NewL();
+	~CReadDriveThread();
+
+private:
+	CReadDriveThread();
+	void ConstructL();
+
+public:
+	TBool ReadDriveData(CMassStorageDrive* aDrive, const TInt64& aOffset, TUint32 aLength, TBool aIgnoreCache);
+	void DiscardRead();
+
+private:
+	static TInt ThreadFunction(TAny* aSelf);
+	TInt ReadFromDrive();
+
+public:
+	/** Thread context */
+	CThreadContext* iThreadContext;
+	TBool iCompleted;
+
+private:
+	TBool iThreadRunning;
+	};
+
+
+//-----------------------------------------------
+
+/**
+Swap the buffer which the read and write buffer pointers are pointing to.
+*/
+inline void TBlockDescBuffer::SwapDesc()
+{
+	TBlockDesc* const tmp = iDescReadPtr;
+	iDescReadPtr = iDescWritePtr;
+	iDescWritePtr = tmp;
+}
+
+inline TPtr8 TBlockDesc::GetReadBuffer()
+{
+	return iBuf.LeftTPtr(iBuf.Length());
+}
+
+
+inline TPtr8 TBlockDesc::GetReadBuffer(TUint aLength, const TInt64& aOffset)
+{
+	iByteOffset = aOffset;
+	iLength = aLength;
+	iBuf.SetLength(aLength);
+	
+	return GetReadBuffer();
+}
+
+//-----------------------------------------------
+
+/**
+Returns the id of the buffer
+
+@param bufferPtr pointer to the buffer.
+@return  returns the buffer ID or -1 if the buffer is not found.
+*/
+inline TInt TBlockDescBuffer::GetBufferNumber(const TPtr8* aBufferPtr) const
+{
+	TInt no = -1;
+	if (aBufferPtr == &iDesc1.iBuf)
+		no = 1;
+	else if (aBufferPtr == &iDesc2.iBuf)
+		no = 2;
+	return no;
+}
+
+
+//-----------------------------------------------
+
+inline TPtr8 CThreadContext::GetReadBuffer()
+{
+	TInt len = iBuffer.iDescReadPtr->iBuf.Length();
+	return iBuffer.iDescReadPtr->iBuf.LeftTPtr(len);
+}
+
+
+inline TPtr8 CThreadContext::GetReadBuffer(TInt aLength)
+{
+	iBuffer.iDescReadPtr->iBuf.SetLength(aLength);
+	return GetReadBuffer();
+}
+
+
+inline TPtrC8 CThreadContext::WriteBuf()
+{
+	return iBuffer.iDescWritePtr->iBuf;
+}
+
+//-----------------------------------------------
+
+inline TBlockDesc* CWriteDriveThread::GetReadDesc()
+{
+	return iThreadContext->iBuffer.iDescReadPtr;
+}
+
+//-----------------------------------------------
+
+#endif //  MSDC_MULTITHREADED
+
+#endif // __RWDRIVETHREAD_H__