--- /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__