sl@0: // Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // SCSI Protocol layer for USB Mass Storage sl@0: // sl@0: // sl@0: sl@0: /** sl@0: @file sl@0: @internalTechnology sl@0: */ sl@0: sl@0: #ifndef __SCSIPROT_H__ sl@0: #define __SCSIPROT_H__ sl@0: sl@0: sl@0: // Header files sl@0: #include "drivemanager.h" sl@0: #include "protocol.h" sl@0: sl@0: // Define MSDC_MULTITHREADED to use Mass Storage multi-threaded (Double-buffering) disk read/writes. sl@0: // smassstorage_db.mmp defines this macro. sl@0: sl@0: #if defined MSDC_MULTITHREADED sl@0: class CWriteDriveThread; sl@0: class CReadDriveThread; sl@0: #endif sl@0: sl@0: sl@0: // Display time taken to write data to disk sl@0: //#define MEASURE_AND_DISPLAY_WRITE_TIME sl@0: // Display time taken to read data from disk sl@0: //#define MEASURE_AND_DISPLAY_READ_TIME sl@0: sl@0: sl@0: // Maximum size for SCSI Read10 Write10 and Verify10 commands sl@0: // Windows requests size of 64K whereas MAC requests size of 128K sl@0: static const TUint32 KMaxBufSize = 128 * 1024; sl@0: sl@0: // Write to media when data is available sl@0: static const TUint32 KDefaultMediaWriteSize = 4 * 1024; sl@0: sl@0: // Use in the HS case a write size of 64KB sl@0: static const TUint32 KHsMediaWriteSize = 64 * 1024; sl@0: sl@0: sl@0: /** sl@0: Sense Info sl@0: */ sl@0: class TSenseInfo sl@0: { sl@0: public: sl@0: // Spec: SCSI Primary Commands 3 (SPC-3) sl@0: // Section 4.5.6 Sense key and sense code defintions sl@0: // Table 27 - Sense key descriptions sl@0: enum TSenseCode sl@0: { sl@0: ENoSense = 0, sl@0: ERecoveredError = 1, sl@0: ENotReady = 2, sl@0: EMediumError = 3, sl@0: EHardwareError = 4, sl@0: EIllegalRequest = 5, sl@0: EUnitAttention = 6, sl@0: EDataProtection = 7, sl@0: EBlankCheck = 8, sl@0: EVendorSpecific = 9, sl@0: ECopyAborted = 10, sl@0: EAbortedCommand = 11, sl@0: EDataOverflow = 13, sl@0: EMisCompare = 14 sl@0: }; sl@0: sl@0: // Table 28 - ASC and ASQ assignments sl@0: enum TAdditionalCode sl@0: { sl@0: EAscNull = 0x00, sl@0: EAscLogicalUnitNotReady = 0x04, sl@0: EAscLogicalUnitDoesNotRespondToSelection = 0x05, sl@0: EInvalidCmdCode = 0x20, sl@0: ELbaOutOfRange = 0x21, sl@0: EInvalidFieldInCdb = 0x24, sl@0: ELuNotSupported = 0x25, sl@0: EWriteProtected = 0x27, sl@0: ENotReadyToReadyChange = 0x28, sl@0: EMediaNotPresent = 0x3A, sl@0: EInsufficientRes = 0x55 sl@0: }; sl@0: sl@0: enum TAdditionalSenseCodeQualifier sl@0: { sl@0: EAscqNull = 0x00, sl@0: EAscqLogicalUnitIsInProcessOfBecomingReady = 0x01 sl@0: }; sl@0: sl@0: public: sl@0: TSenseInfo(); sl@0: sl@0: void SetSense(TSenseCode aSenseCode); sl@0: sl@0: void SetSense(TSenseCode aSenseCode, sl@0: TAdditionalCode aAdditional); sl@0: sl@0: void SetSense(TSenseCode aSenseCode, sl@0: TAdditionalCode aAdditional, sl@0: TAdditionalSenseCodeQualifier aQualifier); sl@0: sl@0: TBool SenseOk(); sl@0: sl@0: public: sl@0: TUint8 iSenseCode; sl@0: TUint8 iAdditional; sl@0: TUint8 iQualifier; sl@0: }; sl@0: sl@0: sl@0: /** sl@0: Returns EFalse if a sense code has been set. sl@0: Note that ENoSense indicates that there is no specific sense key infotmation sl@0: to be reported and the command was successful. sl@0: */ sl@0: inline TBool TSenseInfo::SenseOk() sl@0: { sl@0: return (iSenseCode == ENoSense); sl@0: } sl@0: sl@0: sl@0: const TUint KModeSenseCommandLength = 4; sl@0: const TUint KReadCapacityCommandLength = 8; sl@0: const TUint KReadFormatCapacitiesCommandLength = 12; sl@0: const TUint KRequestSenseCommandLength = 18; sl@0: const TUint KInquiryCommandLength = 36; sl@0: sl@0: sl@0: /** sl@0: The CScsiProtocol is responsible for interpreting the data received from the Transpor layer sl@0: and where appropriate routing specific requests through to the appropriate drive unit. sl@0: sl@0: @internalTechnology sl@0: */ sl@0: class CScsiProtocol : public CBase, public MProtocolBase sl@0: { sl@0: public: sl@0: enum TCommand sl@0: { sl@0: ETestUnitReady = 0x00, sl@0: ERequestSense = 0x03, sl@0: EInquiry = 0x12, sl@0: EModeSense = 0x1A, sl@0: EStartStopUnit = 0x1B, sl@0: EPreventMediaRemoval = 0x1E, sl@0: EReadFormatCapacities = 0x23, sl@0: EReadCapacity = 0x25, sl@0: ERead10 = 0x28, sl@0: EWrite10 = 0x2A, sl@0: EVerify10 = 0x2f, sl@0: EUndefinedCommand = 0xFF sl@0: }; sl@0: sl@0: sl@0: public: sl@0: sl@0: static CScsiProtocol* NewL(CDriveManager& aDriveManager); sl@0: void RegisterTransport(MTransportBase* aTransport); sl@0: void ReportHighSpeedDevice(); sl@0: TBool DecodePacket(TPtrC8& aData, TUint aLun); sl@0: TInt ReadComplete(TInt aError); sl@0: TInt SetScsiParameters(TMassStorageConfig aConfig); sl@0: TInt Cancel(); sl@0: ~CScsiProtocol(); sl@0: sl@0: #ifdef MSDC_MULTITHREADED sl@0: void InitializeBufferPointers(TPtr8& aDes1, TPtr8& aDes2); sl@0: static void ProcessWriteComplete (TUint8* aAddress, TAny* aPtr); //todo const sl@0: #endif sl@0: sl@0: private: sl@0: CScsiProtocol(CDriveManager& aDriveManager); sl@0: void ConstructL(); sl@0: CMassStorageDrive* GetCheckDrive(TUint aLun); sl@0: TBool HandleUnitReady(TUint aLun); sl@0: TBool HandleRequestSense(TPtrC8& aData); sl@0: TBool HandleInquiry(TPtrC8& aData, TUint aLun); sl@0: TBool HandleStartStopUnit(TPtrC8& aData, TUint aLun); sl@0: TBool HandlePreventMediaRemoval(TPtrC8& aData, TUint aLun); sl@0: TBool HandleReadCapacity(TPtrC8& aData, TUint aLun); sl@0: TBool HandleRead10(TPtrC8& aData, TUint aLun); sl@0: TBool HandleWrite10(TPtrC8& aData, TUint aLun); sl@0: TBool HandleVerify10(TPtrC8& aData, TUint aLun); sl@0: TBool HandleModeSense(TPtrC8& aData, TUint aLun); sl@0: TBool HandleReadFormatCapacities(TUint aLun); sl@0: sl@0: private: sl@0: /** Configuration data for INQUIRY command*/ sl@0: TMassStorageConfig iConfig; sl@0: sl@0: /** reference to the Drive Manager */ sl@0: CDriveManager& iDriveManager; sl@0: sl@0: /** pointer to the transport level */ sl@0: MTransportBase* iTransport; sl@0: sl@0: /** Sense Info */ sl@0: TSenseInfo iSenseInfo; sl@0: sl@0: #ifdef MSDC_MULTITHREADED sl@0: /** Sense Info */ sl@0: TSenseInfo iDeferredSenseInfo; sl@0: #endif sl@0: sl@0: /** Start offset (in bytes) for Write/Verify */ sl@0: TInt64 iOffset; sl@0: sl@0: /** Last command for SetupRead (Write or Verify) */ sl@0: TUint8 iLastCommand; sl@0: sl@0: /** LUN for SetupRead */ sl@0: TUint iLastLun; sl@0: sl@0: #ifdef SIMDISK sl@0: CArrayFixFlat* iSimDisk; sl@0: #endif sl@0: sl@0: /** The number of bytes remaining to be read from the host for write operations */ sl@0: TUint32 iBytesRemain; sl@0: sl@0: /** Write to the media when this amount of data is available */ sl@0: TUint32 iMediaWriteSize; sl@0: sl@0: #ifdef MSDC_MULTITHREADED sl@0: /** Ptr to Write Thread instance */ sl@0: CWriteDriveThread* iWriteDriveThread; sl@0: sl@0: /** Ptr to Read Thread instance */ sl@0: CReadDriveThread* iReadDriveThread; sl@0: #endif // MSDC_MULTITHREADED sl@0: sl@0: #ifdef USB_TRANSFER_PUBLISHER sl@0: /** sl@0: Publish and subscribe properties for tracking data transfer volume sl@0: */ sl@0: CUsbWriteTransferPublisher* iWriteTransferPublisher; sl@0: CUsbReadTransferPublisher* iReadTransferPublisher; sl@0: sl@0: /** sl@0: Cumulative bytes read sl@0: */ sl@0: TFixedArray iBytesRead; sl@0: /** sl@0: Cumulative bytes written sl@0: */ sl@0: TFixedArray iBytesWritten; sl@0: #else sl@0: /** sl@0: Publish and subscribe properties for tracking data transfer volume sl@0: */ sl@0: CDriveWriteTransferPublisher* iWriteTransferPublisher; sl@0: CDriveReadTransferPublisher* iReadTransferPublisher; sl@0: #endif sl@0: }; sl@0: sl@0: #endif // __SCSIPROT_H__