usbclasses/usbphoneasmodem/classimplementation/mscfileserver/inc/scsiprot.h
author William Roberts <williamr@symbian.org>
Thu, 22 Jul 2010 16:44:03 +0100
branchGCC_SURGE
changeset 63 ef2686f7597e
parent 2 468cfcb53fd1
parent 35 9d8b04ca6939
permissions -rw-r--r--
Catchup to latest Symbian^4

// Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of "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: SCSI Protocol layer for USB Mass Storage
// 
// 

#ifndef SCSIPROT_H
#define SCSIPROT_H


// Header files
#include "filesystemimage.h"
#include "protocol.h"
#include "mscfilecontroller.h"
#include "usbmscfileshared.h"

// Define MSDC_MULTITHREADED to use Mass Storage multi-threaded (Double-buffering) disk read/writes.
// smassstorage_db.mmp defines this macro.


// Display time taken to write data to disk
//#define MEASURE_AND_DISPLAY_WRITE_TIME
// Display time taken to read data from disk
//#define MEASURE_AND_DISPLAY_READ_TIME


// Maximum size for SCSI Read10 Write10 and Verify10 commands
// Windows requests size of 64K whereas MAC requests size of 128K
static const TUint32 KMaxBufSize = 128 * 1024;

// Write to media when data is available
static const TUint32 KDefaultMediaWriteSize = 4 * 1024;

// Use in the HS case a write size of 64KB
static const TUint32 KHsMediaWriteSize = 64 * 1024;


/**
Sense Info
*/
class TSenseInfo
	{
public:
	// Spec: SCSI Primary Commands 3 (SPC-3)
	// Section 4.5.6 Sense key and sense code defintions
	// Table 27 - Sense key descriptions
	enum TSenseCode
		{
		ENoSense        = 0,
		ERecoveredError = 1,
		ENotReady       = 2,
		EMediumError    = 3,
		EHardwareError  = 4,
		EIllegalRequest = 5,
		EUnitAttention  = 6,
		EDataProtection = 7,
		EBlankCheck     = 8,
		EVendorSpecific = 9,
		ECopyAborted    = 10,
		EAbortedCommand = 11,
		EDataOverflow   = 13,
		EMisCompare     = 14
		};

	// Table 28 - ASC and ASQ assignments
	enum TAdditionalCode
		{
		EAscNull								 = 0x00,
		EAscLogicalUnitNotReady					 = 0x04,
		EAscLogicalUnitDoesNotRespondToSelection = 0x05,
		EInvalidCmdCode							 = 0x20,
		ELbaOutOfRange							 = 0x21,
		EInvalidFieldInCdb						 = 0x24,
		ELuNotSupported							 = 0x25,
		EWriteProtected							 = 0x27,
		ENotReadyToReadyChange					 = 0x28,
		EMediaNotPresent						 = 0x3A,
		EInsufficientRes						 = 0x55
		};

	enum TAdditionalSenseCodeQualifier
		{
		EAscqNull								   = 0x00,
		EAscqLogicalUnitIsInProcessOfBecomingReady = 0x01
		};

public:
	TSenseInfo();

	void SetSense(TSenseCode aSenseCode);

	void SetSense(TSenseCode aSenseCode,
				  TAdditionalCode aAdditional);

	void SetSense(TSenseCode aSenseCode,
				  TAdditionalCode aAdditional,
				  TAdditionalSenseCodeQualifier aQualifier);

	TBool SenseOk();

public:
	TUint8 iSenseCode;
	TUint8 iAdditional;
	TUint8 iQualifier;
	};


/**
Returns EFalse if a sense code has been set. 
Note that ENoSense indicates that there is no specific sense key infotmation
to be reported and the command was successful. 
*/
inline TBool TSenseInfo::SenseOk()
	{
	return (iSenseCode == ENoSense);
	}


const TUint KModeSenseCommandLength = 4;
const TUint KReadCapacityCommandLength = 8;
const TUint KReadFormatCapacitiesCommandLength = 12;
const TUint KRequestSenseCommandLength = 18;
const TUint KInquiryCommandLength = 36;

const TUint KCommandBufferLength = KInquiryCommandLength;


/**
The CScsiProtocol is responsible for interpreting the data received from the Transpor layer
and where appropriate routing specific requests through to the appropriate drive unit.

@internalTechnology
*/
class CScsiProtocol : public CBase, public MProtocolBase
	{
public:
	enum TCommand
	{
    ETestUnitReady          = 0x00,
    ERequestSense           = 0x03,
    EInquiry                = 0x12,
    EModeSense              = 0x1A,
    EStartStopUnit          = 0x1B,
    EPreventMediaRemoval    = 0x1E,
    EReadFormatCapacities   = 0x23, // not supported for CD-ROM
    EReadCapacity           = 0x25,
    ERead10                 = 0x28,
    EWrite10                = 0x2A, // not supported for CD-ROM
    EVerify10               = 0x2f, // not supported for CD-ROM
    EReadTOC                = 0x43,
    EGetConfiguration       = 0x46,
    EModeSense10            = 0x5A,
    ERead12                 = 0xA8,
    EUndefinedCommand       = 0xFF
	};


public:

	static CScsiProtocol* NewL(CMscFileController& aController);
	void RegisterTransport(MTransportBase* aTransport);
	void ReportHighSpeedDevice();
	TBool DecodePacket(TPtrC8& aData, TUint aLun);
	TInt ReadComplete(TInt aError);
	TInt SetScsiParameters(TMassStorageConfig aConfig);
	TInt Cancel();
	~CScsiProtocol();

private:
	CScsiProtocol(CMscFileController& aController);
	void  ConstructL();
	CFileSystemImage* GetCheckFs(TUint aLun);
    TBool HandleUnitReady(TUint aLun);
    TBool HandleRequestSense(TPtrC8& aData);
    TBool HandleInquiry(TPtrC8& aData, TUint aLun);
    TBool HandleStartStopUnit(TPtrC8& aData, TUint aLun);
    TBool HandlePreventMediaRemoval(TPtrC8& aData, TUint aLun);
    TBool HandleReadCapacity(TPtrC8& aData, TUint aLun);
    TBool HandleRead10(TPtrC8& aData, TUint aLun);
    TBool HandleRead12(TPtrC8& aData, TUint aLun);
    TBool HandleModeSense(TPtrC8& aData, TUint aLun);
    TBool HandleModeSense10(TPtrC8& aData, TUint aLun);
    TBool HandleReadTOC(TPtrC8& aData, TUint aLun);
    TBool HandleGetConfiguration(TPtrC8& aData, TUint aLun);

private:
	/** Configuration data for INQUIRY command*/
	TMassStorageConfig iConfig;

	/** reference to the Drive Manager */
	CMscFileController& iController;
	
	/** pointer to the transport level */
	MTransportBase* iTransport; 

	/** Sense Info */
	TSenseInfo iSenseInfo;

	/** General buffer for read/write operations */
	TBuf8<KMaxBufSize> iCommandBuf;

	/** StartL offset (in bytes) for Write/Verify */
	TInt64 iOffset;

	/** Last command for SetupRead (Write or Verify) */
	TUint8 iLastCommand;

	/** LUN for SetupRead */
	TUint iLastLun;

#ifdef SIMDISK
	CArrayFixFlat<TUint8>* iSimDisk;
#endif

	/** The number of bytes remaining to be read from the host for write operations */
	TUint32 iBytesRemain;

	/** Write to the media when this amount of data is available */
	TUint32 iMediaWriteSize;

	};

#endif // SCSIPROT_H