userlibandfileserver/fileserver/smassstorage/scsiprot.cpp
changeset 286 48e57fb1237e
parent 90 947f0dc9f7a8
equal deleted inserted replaced
285:ff5437e4337c 286:48e57fb1237e
    11 // Contributors:
    11 // Contributors:
    12 //
    12 //
    13 // Description:
    13 // Description:
    14 //
    14 //
    15 
    15 
       
    16 #include <e32std.h>
       
    17 #include "mtransport.h"
       
    18 #include "mprotocol.h"
    16 #include "scsiprot.h"
    19 #include "scsiprot.h"
    17 #ifdef MSDC_MULTITHREADED 
    20 #ifdef MSDC_MULTITHREADED
    18 #include "rwdrivethread.h"
    21 #include "rwdrivethread.h"
    19 #endif // MSDC_MULTITHREADED
    22 #endif // MSDC_MULTITHREADED
    20 #include "massstoragedebug.h"
    23 
       
    24 #include "OstTraceDefinitions.h"
       
    25 #ifdef OST_TRACE_COMPILER_IN_USE
       
    26 #include "scsiprotTraces.h"
       
    27 #endif
    21 
    28 
    22 // Helper macros
    29 // Helper macros
    23 #define LBA(x) static_cast<TUint32>((x[3] << 24) | (x[4] << 16) | (x[5] << 8) | x[6])
    30 #define LBA(x) static_cast<TUint32>((x[3] << 24) | (x[4] << 16) | (x[5] << 8) | x[6])
    24 #define LEN(x) static_cast<TUint16>((x[8] << 8) | x[9])
    31 #define LEN(x) static_cast<TUint16>((x[8] << 8) | x[9])
    25 
    32 
    26 
    33 
    27 LOCAL_D const TUint KDefaultBlockSize = 0x200;  //default block size for FAT
    34 static const TUint32 KDefaultBlockSize = 0x200;  //default block size for FAT
    28 
    35 
    29 LOCAL_D const TUint KUndefinedLun = 0xFFFF;
    36 static const TUint KUndefinedLun = 0xFFFF;
    30 
    37 
    31 LOCAL_D const TUint8 KAllPages = 0x3F;
    38 static const TUint8 KAllPages = 0x3F;
    32 
    39 
    33 LOCAL_D const TUint8 KChangeableValues = 0x1;
    40 static const TUint8 KChangeableValues = 0x1;
    34 LOCAL_D const TUint8 KDefaultValues = 0x2;
    41 static const TUint8 KDefaultValues = 0x2;
    35 
    42 
    36 /**
    43 /**
    37 Default constructor for TSenseInfo
    44 Default constructor for TSenseInfo
    38 */
    45 */
    39 TSenseInfo::TSenseInfo()
    46 TSenseInfo::TSenseInfo()
    40 	: iSenseCode(ENoSense),
    47     : iSenseCode(ENoSense),
    41 	  iAdditional(EAscNull),
    48       iAdditional(EAscNull),
    42 	  iQualifier(EAscqNull)
    49       iQualifier(EAscqNull)
    43 	{}
    50     {}
    44 
    51 
    45 
    52 
    46 /**
    53 /**
    47 Set sense with no additional info.
    54 Set sense with no additional info.
    48 
    55 
    49 @param aSenseCode sense key
    56 @param aSenseCode sense key
    50 */
    57 */
    51 void TSenseInfo::SetSense(TSenseCode aSenseCode)
    58 void TSenseInfo::SetSense(TSenseCode aSenseCode)
    52 	{
    59     {
    53 	iSenseCode = static_cast<TUint8>(aSenseCode);
    60     iSenseCode = static_cast<TUint8>(aSenseCode);
    54 	iAdditional = EAscNull;
    61     iAdditional = EAscNull;
    55 	iQualifier = EAscqNull;
    62     iQualifier = EAscqNull;
    56 	}
    63     OstTraceExt3(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_SETSENSE1, "    SENSE CODE %d ASC %d ASC %d", iSenseCode, iAdditional, iQualifier);
       
    64     }
    57 
    65 
    58 
    66 
    59 /**
    67 /**
    60 Set sense with additional info.
    68 Set sense with additional info.
    61 
    69 
    62 @param aSenseCode sense key
    70 @param aSenseCode sense key
    63 @param aAdditional additional sense code (ASC) 
    71 @param aAdditional additional sense code (ASC)
    64 */
    72 */
    65 void TSenseInfo::SetSense(TSenseCode aSenseCode, TAdditionalCode aAdditional)
    73 void TSenseInfo::SetSense(TSenseCode aSenseCode, TAdditionalCode aAdditional)
    66 
    74 
    67 	{
    75     {
    68 	iSenseCode = static_cast<TUint8>(aSenseCode);
    76     iSenseCode = static_cast<TUint8>(aSenseCode);
    69 	iAdditional = static_cast<TUint8>(aAdditional);
    77     iAdditional = static_cast<TUint8>(aAdditional);
    70 	iQualifier = EAscqNull;
    78     iQualifier = EAscqNull;
    71 	}
    79     OstTraceExt3(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_SETSENSE2, "    SENSE CODE %d ASC %d ASC %d", iSenseCode, iAdditional, iQualifier);
       
    80     }
    72 
    81 
    73 
    82 
    74 /**
    83 /**
    75 Set sense with additional info and qualifier.
    84 Set sense with additional info and qualifier.
    76 
    85 
    77 @param aSenseCode sense key 
    86 @param aSenseCode sense key
    78 @param aAdditional additional sense code (ASC) 
    87 @param aAdditional additional sense code (ASC)
    79 @param aQualifier additional sense code qualifier (ASCQ)
    88 @param aQualifier additional sense code qualifier (ASCQ)
    80 */
    89 */
    81 void TSenseInfo::SetSense(TSenseCode aSenseCode,
    90 void TSenseInfo::SetSense(TSenseCode aSenseCode,
    82 						  TAdditionalCode aAdditional,
    91                           TAdditionalCode aAdditional,
    83 						  TAdditionalSenseCodeQualifier aQualifier)
    92                           TAdditionalSenseCodeQualifier aQualifier)
    84 	{
    93     {
    85 	iSenseCode = static_cast<TUint8>(aSenseCode);
    94     iSenseCode = static_cast<TUint8>(aSenseCode);
    86 	iAdditional = static_cast<TUint8>(aAdditional);
    95     iAdditional = static_cast<TUint8>(aAdditional);
    87 	iQualifier = static_cast<TUint8>(aQualifier);
    96     iQualifier = static_cast<TUint8>(aQualifier);
    88 	}
    97     OstTraceExt3(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_SETSENSE3, "    SENSE CODE %d ASC %d ASC %d", iSenseCode, iAdditional, iQualifier);
       
    98     }
    89 
    99 
    90 
   100 
    91 //-----------------------------------------------
   101 //-----------------------------------------------
    92 
   102 
    93 /**
   103 /**
    94 Creates the CScsiProtocol object.  Called during controller initialisation.
   104 Creates the CScsiProtocol object.  Called during controller initialisation.
    95 
   105 
    96 @param aDriveManager reference to the drive manager object
   106 @param aDriveManager reference to the drive manager object
    97 */
   107 */
    98 CScsiProtocol* CScsiProtocol::NewL(CDriveManager& aDriveManager)
   108 CScsiProtocol* CScsiProtocol::NewL(CDriveManager& aDriveManager)
    99 	{
   109     {
   100 	CScsiProtocol* self = new (ELeave) CScsiProtocol(aDriveManager);
   110     CScsiProtocol* self = new (ELeave) CScsiProtocol(aDriveManager);
   101 	CleanupStack::PushL(self);
   111     CleanupStack::PushL(self);
   102 	self->ConstructL();
   112     self->ConstructL();
   103 	CleanupStack::Pop();
   113     CleanupStack::Pop();
   104 	return self;
   114     return self;
   105 	}
   115     }
   106 
   116 
   107 /**
   117 /**
   108 c'tor
   118 c'tor
   109 
   119 
   110 @param aDriveManager reference to the drive manager object
   120 @param aDriveManager reference to the drive manager object
   111 */
   121 */
   112 CScsiProtocol::CScsiProtocol(CDriveManager& aDriveManager):
   122 CScsiProtocol::CScsiProtocol(CDriveManager& aDriveManager):
   113 	iDriveManager(aDriveManager),
   123     iDriveManager(aDriveManager),
   114 	iLastCommand(EUndefinedCommand),
   124     iLastCommand(EUndefinedCommand),
   115 	iLastLun(KUndefinedLun),
   125     iLastLun(KUndefinedLun),
   116 	iMediaWriteSize(KDefaultMediaWriteSize)
   126     iMediaWriteSize(KDefaultMediaWriteSize)
   117 	{
   127     {
   118 	__FNLOG("CScsiProtocol::CScsiProtocol");
       
   119 
       
   120 #ifdef USB_TRANSFER_PUBLISHER
   128 #ifdef USB_TRANSFER_PUBLISHER
   121 	iWriteTransferPublisher = CUsbWriteTransferPublisher::NewL(iBytesWritten);
   129     iWriteTransferPublisher = CUsbWriteTransferPublisher::NewL(iBytesWritten);
   122 	iReadTransferPublisher = CUsbReadTransferPublisher::NewL(iBytesRead);
   130     iReadTransferPublisher = CUsbReadTransferPublisher::NewL(iBytesRead);
   123 
   131 
   124 	for (TUint i = 0; i < KUsbMsMaxDrives; i++)
   132     for (TUint i = 0; i < KUsbMsMaxDrives; i++)
   125 		{
   133         {
   126 		iBytesRead[i] = 0;
   134         iBytesRead[i] = 0;
   127 		iBytesWritten[i] = 0;
   135         iBytesWritten[i] = 0;
   128 		}
   136         }
   129 #else
   137 #else
   130 	iWriteTransferPublisher = CDriveWriteTransferPublisher::NewL(aDriveManager.iDrives);
   138     iWriteTransferPublisher = CDriveWriteTransferPublisher::NewL(aDriveManager.iDrives);
   131 	iReadTransferPublisher = CDriveReadTransferPublisher::NewL(aDriveManager.iDrives);
   139     iReadTransferPublisher = CDriveReadTransferPublisher::NewL(aDriveManager.iDrives);
   132 #endif
   140 #endif
   133 	}
   141     }
   134 
   142 
   135 
   143 
   136 CScsiProtocol::~CScsiProtocol()
   144 CScsiProtocol::~CScsiProtocol()
   137 	{
   145     {
   138 	__FNLOG("CScsiProtocol::~CScsiProtocol");
   146 #ifdef MSDC_MULTITHREADED
   139 #ifdef MSDC_MULTITHREADED
   147     OstTrace0(TRACE_SMASSSTORAGE, CSCSIPROTOCOL_DES, "Deleting Drive Threads");
   140 	__PRINT(_L("Deleting WriteDrive Thread"));
   148     delete iWriteDriveThread;
   141 	delete iWriteDriveThread;
   149     delete iReadDriveThread;
   142 	__PRINT(_L("Deleting ReadDrive Thread"));
       
   143 	delete iReadDriveThread;
       
   144 #endif // MSDC_MULTITHREADED
   150 #endif // MSDC_MULTITHREADED
   145 
   151 
   146 	delete iWriteTransferPublisher;
   152     delete iWriteTransferPublisher;
   147 	delete iReadTransferPublisher;
   153     delete iReadTransferPublisher;
   148 	}
   154     }
   149 
   155 
   150 
   156 
   151 void CScsiProtocol::ConstructL()
   157 void CScsiProtocol::ConstructL()
   152 	{
   158     {
   153 	__FNLOG("CScsiProtocol::ConstructL");
   159 #ifdef MSDC_MULTITHREADED
   154 #ifdef MSDC_MULTITHREADED
   160     OstTrace0(TRACE_SMASSSTORAGE, _CSCSIPROTOCOL, "Creating Drive Threads");
   155 	__PRINT(_L("Creating WriteDrive Thread"));
   161     iWriteDriveThread = CWriteDriveThread::NewL();
   156 	iWriteDriveThread = CWriteDriveThread::NewL();
   162     iReadDriveThread = CReadDriveThread::NewL();
   157 	__PRINT(_L("Creating ReadDrive Thread"));
       
   158 	iReadDriveThread = CReadDriveThread::NewL();
       
   159 #endif // MSDC_MULTITHREADED
   163 #endif // MSDC_MULTITHREADED
   160 	}
   164     }
   161 
   165 
   162 
   166 
   163 /**
   167 /**
   164 Associates the transport with the protocol. Called during initialisation of the controller.
   168 Associates the transport with the protocol. Called during initialisation of the controller.
   165 
   169 
   166 @param aTransport pointer to the transport object
   170 @param aTransport pointer to the transport object
   167 */
   171 */
   168 void CScsiProtocol::RegisterTransport(MTransportBase* aTransport)
   172 void CScsiProtocol::RegisterTransport(MTransportBase* aTransport)
   169 	{
   173     {
   170 	__FNLOG("CScsiProtocol::RegisterTransport");
   174     iTransport = aTransport;
   171 	iTransport = aTransport;
   175     }
   172 	}
       
   173 
   176 
   174 
   177 
   175 /**
   178 /**
   176 Called by the Transport when it detects that the USB device is either running
   179 Called by the Transport when it detects that the USB device is either running
   177 at High Speed or is at least capable of HS operation. The Protocol can use this
   180 at High Speed or is at least capable of HS operation. The Protocol can use this
   180 This function is preferably called before actual MS data transfer operation
   183 This function is preferably called before actual MS data transfer operation
   181 starts, and usually only once.
   184 starts, and usually only once.
   182 
   185 
   183 */
   186 */
   184 void CScsiProtocol::ReportHighSpeedDevice()
   187 void CScsiProtocol::ReportHighSpeedDevice()
   185 	{
   188     {
   186 	__FNLOG("CScsiProtocol::ReportHighSpeedDevice");
   189     iMediaWriteSize = KHsMediaWriteSize;
   187 	iMediaWriteSize = KHsMediaWriteSize;
   190     OstTrace1(TRACE_SMASSSTORAGE, CSCSIPROTOCOL_REPORTHIGHSPEEDDEVICE,
   188 	__PRINT1(_L("HS Device reported: SCSI will use %d bytes disk write size"), iMediaWriteSize);
   191               "HS Device reported: SCSI will use 0x%x bytes disk write size", iMediaWriteSize);
   189 	}
   192     }
   190 
   193 
   191 
   194 
   192 TInt CScsiProtocol::SetScsiParameters(TMassStorageConfig aConfig)
   195 TInt CScsiProtocol::SetScsiParameters(TMassStorageConfig aConfig)
   193 	{
   196     {
   194 	__FNLOG("CScsiProtocol::SetScsiParameters");
   197     iConfig = aConfig;
   195 	iConfig = aConfig;
   198     return KErrNone;
   196 	return KErrNone;
   199     }
   197 	}
       
   198 
   200 
   199 #ifdef MSDC_MULTITHREADED
   201 #ifdef MSDC_MULTITHREADED
   200 
   202 
   201 void CScsiProtocol::ProcessWriteComplete (TUint8* aAddress, TAny* aPtr)
   203 void CScsiProtocol::ProcessWriteComplete (TUint8* aAddress, TAny* aPtr)
   202 	{
   204     {
   203 	((CScsiProtocol*)aPtr)->iTransport->ProcessReadData(aAddress);
   205     ((CScsiProtocol*)aPtr)->iTransport->ProcessReadData(aAddress);
   204 	}
   206     }
   205 
   207 
   206 void CScsiProtocol::InitializeBufferPointers(TPtr8& aDes1, TPtr8& aDes2) // Todo Change name later - InitializeReadBufferSomething
   208 void CScsiProtocol::InitializeBufferPointers(TPtr8& aDes1, TPtr8& aDes2) // Todo Change name later - InitializeReadBufferSomething
   207 	{
   209     {
   208 	iReadDriveThread->iThreadContext->iBuffer.SetUpReadBuf(aDes1, aDes2);
   210     iReadDriveThread->iThreadContext->iBuffer.SetUpReadBuf(aDes1, aDes2);
   209 	}
   211     }
   210 #endif
   212 #endif
   211 
   213 
   212 /**
   214 /**
   213 Called by the transport layer when a packet is available for decoding.
   215 Called by the transport layer when a packet is available for decoding.
   214 If an error occurs, the sense code is updated and EFalse is returned.
   216 If an error occurs, the sense code is updated and EFalse is returned.
   216 @param aData
   218 @param aData
   217 
   219 
   218 @return  ETrue if command was decoded and executed successfully
   220 @return  ETrue if command was decoded and executed successfully
   219 */
   221 */
   220 TBool CScsiProtocol::DecodePacket(TPtrC8& aData, TUint aLun)
   222 TBool CScsiProtocol::DecodePacket(TPtrC8& aData, TUint aLun)
   221 	{
   223     {
   222 	__FNLOG("CScsiProtocol::DecodePacket");
   224     TUint command = aData[1];
   223 
   225 
   224 	TUint8 command = aData[1];
   226     if (command != ERequestSense)
   225 
   227         {
   226 	if (command != ERequestSense)
   228         iSenseInfo.SetSense(TSenseInfo::ENoSense);
   227 		{
   229         }
   228 		iSenseInfo.SetSense(TSenseInfo::ENoSense);
   230 
   229 		}
   231     OstTraceExt2(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_DECODEPACKET, "Command=0x%x LUN=%d", command, aLun);
   230 
   232     switch (command)
   231 	__PRINT2(_L("command = 0x%x lun=%d"), command, aLun);
   233         {
   232 	switch (command)
   234         case ETestUnitReady:
   233 		{
   235             HandleUnitReady(aLun);
   234 		case ETestUnitReady:
   236             break;
   235 			HandleUnitReady(aLun);
   237 
   236 			break;
   238         case ERequestSense:
   237 
   239             HandleRequestSense(aData);
   238 		case ERequestSense:
   240             break;
   239 			HandleRequestSense(aData);
   241 
   240 			break;
   242         case EInquiry:
   241 
   243             HandleInquiry(aData, aLun);
   242 		case EInquiry:
   244             break;
   243 			HandleInquiry(aData, aLun);
   245 
   244 			break;
   246         case EModeSense6:
   245 
   247             HandleModeSense6(aData, aLun);
   246 		case EModeSense6:
   248             break;
   247 			HandleModeSense6(aData, aLun);
       
   248 			break;
       
   249 
   249 
   250         case EModeSense10:
   250         case EModeSense10:
   251             HandleModeSense10(aData, aLun);
   251             HandleModeSense10(aData, aLun);
   252             break;
   252             break;
   253 
   253 
   254 		case EStartStopUnit:
   254         case EStartStopUnit:
   255 			HandleStartStopUnit(aData, aLun);
   255             HandleStartStopUnit(aData, aLun);
   256 			break;
   256             break;
   257 
   257 
   258 		case EPreventMediaRemoval:
   258         case EPreventMediaRemoval:
   259 			HandlePreventMediaRemoval(aData, aLun);
   259             HandlePreventMediaRemoval(aData, aLun);
   260 			break;
   260             break;
   261 
   261 
   262 		case EReadCapacity:
   262         case EReadCapacity:
   263 			HandleReadCapacity(aData, aLun);
   263             HandleReadCapacity(aData, aLun);
   264 			break;
   264             break;
   265 
   265 
   266 		case ERead10:
   266         case ERead10:
   267 			HandleRead10(aData, aLun);
   267             HandleRead10(aData, aLun);
   268 			break;
   268             break;
   269 
   269 
   270 		case EWrite10:
   270         case EWrite10:
   271 			HandleWrite10(aData,aLun);
   271             HandleWrite10(aData,aLun);
   272 			break;
   272             break;
   273 
   273 
   274 		case EVerify10:
   274         case EVerify10:
   275 			HandleVerify10(aData, aLun);
   275             HandleVerify10(aData, aLun);
   276 			break;
   276             break;
   277 
   277 
   278 		case EReadFormatCapacities:
   278         case EReadFormatCapacities:
   279 			HandleReadFormatCapacities(aLun);
   279             HandleReadFormatCapacities(aLun);
   280 			break;
   280             break;
   281 
   281 
   282 		default:
   282         default:
   283 			iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidCmdCode);
   283             iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidCmdCode);
   284 		}
   284         }
   285 	__PRINT1(_L("DecodePacket result = %d"), iSenseInfo.SenseOk());
   285     return(iSenseInfo.SenseOk());
   286 	return(iSenseInfo.SenseOk());
   286     }
   287 	}
       
   288 
   287 
   289 
   288 
   290 /**
   289 /**
   291 Checks if drive ready
   290 Checks if drive ready
   292 
   291 
   293 @param aLun Logic unit number 
   292 @param aLun Logic unit number
   294 @return pointer to drive correspondent to LUN if drive mounted and ready, NULL otherwise
   293 @return pointer to drive correspondent to LUN if drive mounted and ready, NULL otherwise
   295 */
   294 */
   296 CMassStorageDrive* CScsiProtocol::GetCheckDrive(TUint aLun)
   295 CMassStorageDrive* CScsiProtocol::GetCheckDrive(TUint aLun)
   297 	{
   296     {
   298 	__FNLOG("CScsiProtocol::GetCheckDrive");
   297     TInt err=KErrNone;
   299 	TInt err=KErrNone;
   298 
   300 
   299 #ifdef MSDC_MULTITHREADED
   301 #ifdef MSDC_MULTITHREADED
   300     // check for deferred errors
   302 	// check for deferred errors
   301     if (iWriteDriveThread->DeferredError())
   303 	if (iWriteDriveThread->DeferredError())
   302         {
   304 		{
   303         iWriteDriveThread->ClearDeferredError();
   305 		iWriteDriveThread->ClearDeferredError();
   304         iDeferredSenseInfo.SetSense(TSenseInfo::EMediumError);
   306 		iDeferredSenseInfo.SetSense(TSenseInfo::EMediumError);
   305         return NULL;
   307 		return NULL;
   306         }
   308 		}
   307 
   309 
   308 #endif
   310 #endif
   309 
   311 
   310     CMassStorageDrive* drive= iDriveManager.Drive(aLun, err);
   312 	CMassStorageDrive* drive= iDriveManager.Drive(aLun, err);
   311 
   313 
   312     if (err !=KErrNone || drive == NULL)
   314 	if (err !=KErrNone || drive == NULL)
   313         {
   315 		{
   314         OstTrace0(TRACE_SMASSSTORAGE, CSCSIPROTOCOL_GETCHECKDRIVE1, "No drive available");
   316 		__PRINT(_L("No drive available\n"));
   315         iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::ELuNotSupported);
   317 		iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::ELuNotSupported);
   316         return NULL;
   318 		return NULL;
   317         }
   319 		}
   318 
   320 
   319     CMassStorageDrive::TMountState mountState = drive->MountState();
   321 	CMassStorageDrive::TMountState mountState = drive->MountState();
   320 
   322 
   321     if (mountState == CMassStorageDrive::EDisconnected || mountState == CMassStorageDrive::EConnecting)
   323 	if (mountState == CMassStorageDrive::EDisconnected || mountState == CMassStorageDrive::EConnecting)
   322         {
   324 		{
   323         OstTrace0(TRACE_SMASSSTORAGE, CSCSIPROTOCOL_GETCHECKDRIVE2, "Drive disconnected");
   325 		__PRINT(_L("Drive disconnected\n"));
   324         iSenseInfo.SetSense(TSenseInfo::ENotReady,
   326 		iSenseInfo.SetSense(TSenseInfo::ENotReady,
   325                             TSenseInfo::EMediaNotPresent);
   327 							TSenseInfo::EMediaNotPresent);
   326         return NULL;
   328 		return NULL;
   327         }
   329 		}
   328 
   330 
   329     CMassStorageDrive::TDriveState state = drive->CheckDriveState();
   331 	CMassStorageDrive::TDriveState state = drive->CheckDriveState();
   330     if (state == CMassStorageDrive::EMediaNotPresent || state == CMassStorageDrive::ELocked)
   332 	if (state == CMassStorageDrive::EMediaNotPresent || state == CMassStorageDrive::ELocked)
   331         {
   333 		{
   332         OstTrace1(TRACE_SMASSSTORAGE, CSCSIPROTOCOL_GETCHECKDRIVE3, "Media not present or locked. state =0x%X", state);
   334 		__PRINT1(_L("Media not present or locked. (state =0x%X)\n"),state);
   333         iSenseInfo.SetSense(TSenseInfo::ENotReady, TSenseInfo::EMediaNotPresent);
   335 		iSenseInfo.SetSense(TSenseInfo::ENotReady, TSenseInfo::EMediaNotPresent);
   334         return NULL;
   336 		return NULL;
   335         }
   337 		}
   336 
   338 
   337     if (drive->IsMediaChanged(ETrue))  //reset "media changed" status
   339 	if (drive->IsMediaChanged(ETrue))  //reset "media changed" status
   338         {
   340 		{
   339         OstTrace0(TRACE_SMASSSTORAGE, CSCSIPROTOCOL_GETCHECKDRIVE4, "Media was changed");
   341 		__PRINT(_L("Media was changed\n"));
   340         // SAM-2 Section 5.9.5 Unit Attention Condition
   342 		// SAM-2 Section 5.9.5 Unit Attention Condition
   341         iSenseInfo.SetSense(TSenseInfo::EUnitAttention, TSenseInfo::ENotReadyToReadyChange);
   343 		iSenseInfo.SetSense(TSenseInfo::EUnitAttention, TSenseInfo::ENotReadyToReadyChange);
   342         iDriveManager.Connect(aLun);   //publish event to USB app
   344 		iDriveManager.Connect(aLun);   //publish event to USB app
   343         return NULL;
   345 		return NULL;
   344         }
   346 		}
   345 
   347 
   346     if (mountState == CMassStorageDrive::EDisconnecting)
   348 	if (mountState == CMassStorageDrive::EDisconnecting)
   347         {
   349 		{
   348         OstTrace0(TRACE_SMASSSTORAGE, CSCSIPROTOCOL_GETCHECKDRIVE5, "Drive disconnecting");
   350 		__PRINT(_L("Drive disconnecting\n"));
   349         iSenseInfo.SetSense(TSenseInfo::ENotReady,
   351 		iSenseInfo.SetSense(TSenseInfo::ENotReady,
   350                             TSenseInfo::EMediaNotPresent);
   352 							TSenseInfo::EMediaNotPresent);
   351         return NULL;
   353 		return NULL;
   352         }
   354 		}
   353 
   355 
   354     return drive;
   356 	return drive;
   355     }
   357 	}
       
   358 
   356 
   359 
   357 
   360 /**
   358 /**
   361 Command Parser for the UNIT READY command (0x00)
   359 Command Parser for the UNIT READY command (0x00)
   362 
   360 
   363 @param aLun Logic unit number 
   361 @param aLun Logic unit number
   364 @return ETrue if successful, 
   362 @return ETrue if successful,
   365 */
   363 */
   366 TBool CScsiProtocol::HandleUnitReady(TUint aLun)
   364 TBool CScsiProtocol::HandleUnitReady(TUint aLun)
   367 	{
   365     {
   368 	__FNLOG("CScsiProtocol::HandleUnitReady");
   366     OstTrace0(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_TESTUNITREADY, ">>> TEST UNIT READY");
   369 #ifdef MSDC_MULTITHREADED
   367 #ifdef MSDC_MULTITHREADED
   370 	iWriteDriveThread->WaitForWriteEmpty();
   368     iWriteDriveThread->WaitForWriteEmpty();
   371 #endif
   369 #endif
   372 	return GetCheckDrive(aLun) ? (TBool)ETrue : (TBool)EFalse;
   370     return GetCheckDrive(aLun) ? (TBool)ETrue : (TBool)EFalse;
   373 	}
   371     }
   374 
   372 
   375 
   373 
   376 /**
   374 /**
   377 Command Parser for the REQUEST SENSE command (0x03)
   375 Command Parser for the REQUEST SENSE command (0x03)
   378 
   376 
   379 @return ETrue if successful, 
   377 @return ETrue if successful,
   380 */
   378 */
   381 TBool CScsiProtocol::HandleRequestSense(TPtrC8& aData)
   379 TBool CScsiProtocol::HandleRequestSense(TPtrC8& aData)
   382 	{
   380     {
   383 	__FNLOG("CScsiProtocol::HandleRequestSense");
   381     OstTrace0(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_REQUESTSENSE, ">>> REQUEST SENSE");
   384 	TUint length = aData[5];
   382     TUint length = aData[5];
   385 	__PRINT1(_L("length = %d\n"), length);
   383     OstTrace1(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_REQUESTSENSE1, "    length = %d", length);
   386 	
   384 
   387 	TPtr8 writeBuf(NULL, 0);
   385     TPtr8 writeBuf(NULL, 0);
   388 	iTransport->GetCommandBufPtr(writeBuf, KRequestSenseCommandLength);
   386     iTransport->GetCommandBufPtr(writeBuf, KRequestSenseCommandLength);
   389 	writeBuf.FillZ(KRequestSenseCommandLength);
   387     writeBuf.FillZ(KRequestSenseCommandLength);
   390 
   388 
   391 	TSenseInfo* senseInfo;
   389     TSenseInfo* senseInfo;
   392 #ifdef MSDC_MULTITHREADED
   390 #ifdef MSDC_MULTITHREADED
   393 	if (!iDeferredSenseInfo.SenseOk())
   391     if (!iDeferredSenseInfo.SenseOk())
   394 		{
   392         {
   395 		writeBuf[00] = 0x71; //(deferred errors)
   393         writeBuf[00] = 0x71; //(deferred errors)
   396 		senseInfo = &iDeferredSenseInfo;
   394         senseInfo = &iDeferredSenseInfo;
   397 		}
   395         }
   398 	else
   396     else
   399 		{
   397         {
   400 		writeBuf[00] = 0x70; //(current errors)
   398         writeBuf[00] = 0x70; //(current errors)
   401 		senseInfo = &iSenseInfo;
   399         senseInfo = &iSenseInfo;
   402 		}
   400         }
   403 #else
   401 #else
   404 	senseInfo = &iSenseInfo;
   402     senseInfo = &iSenseInfo;
   405 	writeBuf[00] = 0x70; //(current errors)
   403     writeBuf[00] = 0x70; //(current errors)
   406 #endif
   404 #endif
   407 
   405 
   408 	writeBuf[02] = static_cast<TUint8>(senseInfo->iSenseCode & 0x0F);
   406     writeBuf[02] = static_cast<TUint8>(senseInfo->iSenseCode & 0x0F);
   409 
   407 
   410 	writeBuf[12] = senseInfo->iAdditional;
   408     writeBuf[12] = senseInfo->iAdditional;
   411 	writeBuf[13] = senseInfo->iQualifier;
   409     writeBuf[13] = senseInfo->iQualifier;
   412 	if (length<18 && length >=8) 
   410     if (length<18 && length >=8)
   413 		{
   411         {
   414 		writeBuf.SetLength(length);  //length of response code data
   412         writeBuf.SetLength(length);  //length of response code data
   415 		writeBuf[07] = TUint8(length - 8);  //additional sence length
   413         writeBuf[07] = TUint8(length - 8);  //additional sence length
   416 		}
   414         }
   417 	else if (length >= KRequestSenseCommandLength)
   415     else if (length >= KRequestSenseCommandLength)
   418 		{
   416         {
   419 		writeBuf[07] = KRequestSenseCommandLength - 8;	// we have max 18 byte to send
   417         writeBuf[07] = KRequestSenseCommandLength - 8;  // we have max 18 byte to send
   420 		}
   418         }
   421 
   419 
   422 	__PRINT4(_L("Response=0x%x Sense=0x%x, Additional=0x%x, Qualifier=0x%x\n"),
   420     OstTraceExt4(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_REQUESTSENSE2,
   423 				writeBuf[0], writeBuf[02], writeBuf[12], writeBuf[13]);
   421              "    Response=0x%x Sense=0x%x, Additional=0x%x, Qualifier=0x%x",
   424  
   422              (TUint)writeBuf[0], (TUint)writeBuf[02], (TUint)writeBuf[12], (TUint)writeBuf[13]);
   425 	TPtrC8 writeBuf1 = writeBuf.Left(length);
   423 
   426 
   424     TPtrC8 writeBuf1 = writeBuf.Left(length);
   427 	iTransport->SetupWriteData(writeBuf1);
   425 
   428 
   426     iTransport->SetupWriteData(writeBuf1);
   429 	// clear the sense info
   427 
   430 	iSenseInfo.SetSense(TSenseInfo::ENoSense);
   428     // clear the sense info
   431 
   429     iSenseInfo.SetSense(TSenseInfo::ENoSense);
   432 #ifdef MSDC_MULTITHREADED
   430 
   433 	iDeferredSenseInfo.SetSense(TSenseInfo::ENoSense);
   431 #ifdef MSDC_MULTITHREADED
   434 #endif
   432     iDeferredSenseInfo.SetSense(TSenseInfo::ENoSense);
   435 
   433 #endif
   436 	return ETrue;
   434 
   437 	}
   435     return ETrue;
       
   436     }
   438 
   437 
   439 
   438 
   440 /**
   439 /**
   441 Command Parser for the INQUIRY command (0x12)
   440 Command Parser for the INQUIRY command (0x12)
   442 
   441 
   443 @param aLun Logic unit number 
   442 @param aLun Logic unit number
   444 @return ETrue if successful, 
   443 @return ETrue if successful,
   445 */
   444 */
   446 TBool CScsiProtocol::HandleInquiry(TPtrC8& aData, TUint  aLun )
   445 TBool CScsiProtocol::HandleInquiry(TPtrC8& aData, TUint  aLun )
   447 	{
   446     {
   448 	__FNLOG("CScsiProtocol::HandleInquiry");
   447     OstTrace0(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_INQUIRY, ">>> INQUIRY");
   449 
   448     TBool cmdDt = aData[2] & 0x2;
   450 	TBool cmdDt = aData[2] & 0x2;
   449     TBool evpd  = aData[2] & 0x1;
   451 	TBool evpd  = aData[2] & 0x1;
   450     TUint8 page = aData[3];
   452 	TUint8 page = aData[3];
   451     if (cmdDt || evpd || page || aLun >= KUsbMsMaxDrives)
   453 	if (cmdDt || evpd || page || aLun >= KUsbMsMaxDrives)
   452         {
   454 		{
   453         iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb);
   455 		iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb); 
   454         return EFalse;
   456 		return EFalse;
   455         }
   457 		}
   456 
   458 
   457     TPtr8 writeBuf(NULL, 0);
   459 	TPtr8 writeBuf(NULL, 0);
   458     iTransport->GetCommandBufPtr(writeBuf, KInquiryCommandLength);
   460 	iTransport->GetCommandBufPtr(writeBuf, KInquiryCommandLength);
   459     writeBuf.FillZ(KInquiryCommandLength);
   461 	writeBuf.FillZ(KInquiryCommandLength);
   460 
   462 
   461     writeBuf[1] = 0x80; // MSB: RMB : Removable
   463 	writeBuf[1] = 0x80;	// MSB: RMB : Removable
   462     writeBuf[3] = 0x02; // AERC, TrmTsk, NormACA, Response Data Format
   464 	writeBuf[3] = 0x02;	// AERC, TrmTsk, NormACA, Response Data Format
   463     writeBuf[4] = 0x1F; // Additional Length
   465 	writeBuf[4] = 0x1F;	// Additional Length
   464 
   466 
   465     TPtr8 vendorId(&writeBuf[8], 8, 8);     // Vendor ID (Vendor Specific/Logged by T10)
   467 	TPtr8 vendorId(&writeBuf[8], 8, 8);		// Vendor ID (Vendor Specific/Logged by T10)
   466     vendorId.Fill(' ', 8);
   468 	vendorId.Fill(' ', 8);
   467     vendorId.Copy(iConfig.iVendorId);
   469 	vendorId.Copy(iConfig.iVendorId);
   468 
   470 
   469     TPtr8 productId(&writeBuf[16], 16, 16); // Product ID (Vendor Specific)
   471 	TPtr8 productId(&writeBuf[16], 16, 16);	// Product ID (Vendor Specific)
   470     productId.Fill(' ', 16);
   472 	productId.Fill(' ', 16);
   471     productId.Copy(iConfig.iProductId);
   473 	productId.Copy(iConfig.iProductId);
   472 
   474 
   473     TPtr8 productRev(&writeBuf[32], 4, 4);      // Product Revision Level (Vendor Specific)
   475 	TPtr8 productRev(&writeBuf[32], 4, 4);		// Product Revision Level (Vendor Specific)
   474     productRev.Fill(' ', 4);
   476 	productRev.Fill(' ', 4);
   475     productRev.Copy(iConfig.iProductRev);
   477 	productRev.Copy(iConfig.iProductRev);
   476 
       
   477     OstTraceData(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_INQUIRY1, "Vendor ID %s", vendorId.Ptr(), vendorId.Length());
       
   478     OstTraceData(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_INQUIRY2, "Product ID %s", productId.Ptr(), productId.Length());
       
   479     OstTraceData(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_INQUIRY3, "Product Rev %s", productRev.Ptr(), productRev.Length());
   478 
   480 
   479     TUint length = aData[5];
   481     TUint length = aData[5];
   480 
   482 
   481 	TPtrC8 writeBuf1 = writeBuf.Left(length);
   483     TPtrC8 writeBuf1 = writeBuf.Left(length);
   482 	iTransport->SetupWriteData(writeBuf1);
   484     iTransport->SetupWriteData(writeBuf1);
   483 
   485 
   484 	iSenseInfo.SetSense(TSenseInfo::ENoSense); 
   486     iSenseInfo.SetSense(TSenseInfo::ENoSense);
   485 	return ETrue;
   487     return ETrue;
   486 	}
   488     }
   487 
   489 
   488 
   490 
   489 /**
   491 /**
   490  Command Parser for the START STOP UNIT command (0x1B)
   492  Command Parser for the START STOP UNIT command (0x1B)
   491  
   493 
   492  @param aData command data (started form position 1)
   494  @param aData command data (started form position 1)
   493  @param aLun Logic unit number 
   495  @param aLun Logic unit number
   494  @return ETrue if successful, TFalse otherwise
   496  @return ETrue if successful, TFalse otherwise
   495  */
   497  */
   496 TBool CScsiProtocol::HandleStartStopUnit(TPtrC8& aData, TUint aLun)
   498 TBool CScsiProtocol::HandleStartStopUnit(TPtrC8& aData, TUint aLun)
   497 	{
   499     {
   498 	__FNLOG("CScsiProtocol::HandleStartStopUnit");
   500     OstTrace0(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_STARTSTOPUNIT, ">>> START STOP UNIT");
   499 
   501     const TUint8 KStartMask = 0x01;
   500 	const TUint8 KStartMask = 0x01;
   502     const TUint8 KImmedMask = 0x01;
   501 	const TUint8 KImmedMask = 0x01;
   503     const TUint8 KLoejMask = 0x02;
   502 	const TUint8 KLoejMask = 0x02;
   504 
   503 
   505     TBool immed = aData[2] & KImmedMask ? (TBool)ETrue : (TBool)EFalse;
   504 	TBool immed = aData[2] & KImmedMask ? (TBool)ETrue : (TBool)EFalse;
   506     TBool start = aData[5] & KStartMask ? (TBool)ETrue : (TBool)EFalse;
   505 	TBool start = aData[5] & KStartMask ? (TBool)ETrue : (TBool)EFalse;
   507     TBool loej = aData[5] & KLoejMask ? (TBool)ETrue : (TBool)EFalse;
   506 	TBool loej = aData[5] & KLoejMask ? (TBool)ETrue : (TBool)EFalse;
   508 
   507 
   509     OstTrace1(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_STARTSTOPUNIT1, "    IMMED = %d", immed);
   508 	__PRINT2(_L("Data %X %X\n"), aData[2], aData[5]);
   510     OstTrace1(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_STARTSTOPUNIT2, "    START = %d", start);
   509 	__PRINT1(_L("IMMED = %d\n"), immed);
   511     OstTrace1(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_STARTSTOPUNIT3, "    LOEJ = %d", loej);
   510 	__PRINT1(_L("START = %d\n"), start);
   512 
   511 
   513     TInt err(KErrNone);
   512 	__PRINT1(_L("LOEJ = %d\n"), loej);
   514     if (loej)
   513 
   515         {
   514 	TInt err(KErrNone);
   516         if(start)   //Start unit
   515 	if (loej)
   517             {
   516 		{
   518             err = iDriveManager.Connect(aLun);
   517 		if(start)	//Start unit
       
   518 			{
       
   519 			err = iDriveManager.Connect(aLun);
       
   520 			__PRINT(_L("Load media\n"));
       
   521 
   519 
   522 #ifdef USB_TRANSFER_PUBLISHER
   520 #ifdef USB_TRANSFER_PUBLISHER
   523 			iBytesRead[aLun] = 0;
   521             iBytesRead[aLun] = 0;
   524 			iBytesWritten[aLun] = 0;
   522             iBytesWritten[aLun] = 0;
   525 #endif
   523 #endif
   526 			// publish the initial values
   524             // publish the initial values
   527 			iWriteTransferPublisher->DoPublishDataTransferredEvent();
   525             iWriteTransferPublisher->DoPublishDataTransferredEvent();
   528 			iReadTransferPublisher->DoPublishDataTransferredEvent();
   526             iReadTransferPublisher->DoPublishDataTransferredEvent();
   529 			}
   527             }
   530 		else		//Stop unit 
   528         else        //Stop unit
   531 			{
   529             {
   532 			iDriveManager.SetCritical(aLun, EFalse);
   530             iDriveManager.SetCritical(aLun, EFalse);
   533 			err = iDriveManager.Disconnect(aLun);
   531             err = iDriveManager.Disconnect(aLun);
   534 			__PRINT(_L("Unload media\n"));
   532             }
   535 			}
   533         }
   536 		}
   534 
   537 
   535     if (err !=KErrNone)  //actually we have error here only if the LUN is incorrect
   538 	if (err !=KErrNone)  //actually we have error here only if the LUN is incorrect 
   536         {
   539 		{
   537         iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::ELuNotSupported);
   540 		iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::ELuNotSupported);
   538         return EFalse;
   541 		return EFalse;
   539         }
   542 		}
   540     if (immed)
   543 	if (immed)
   541         {
   544 		{
   542         return ETrue;
   545 		return ETrue;
   543         }
   546 		}
   544 
   547 
   545     CMassStorageDrive* drive= iDriveManager.Drive(aLun, err);
   548 	CMassStorageDrive* drive= iDriveManager.Drive(aLun, err);
   546 
   549 
   547     if (err !=KErrNone || drive == NULL)
   550 	if (err !=KErrNone || drive == NULL)
   548         {
   551 		{
   549         iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::ELuNotSupported);
   552 		iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::ELuNotSupported);
   550         return EFalse;
   553 		return EFalse;
   551         }
   554 		}
   552 
   555 
   553     TInt  timeLeft (20);   // 1 sec timeout
   556 	TInt  timeLeft (20);   // 1 sec timeout
   554     CMassStorageDrive::TMountState mountState;
   557 	CMassStorageDrive::TMountState mountState;
   555 
   558 
   556     do
   559 	do 
   557         {
   560 		{
   558         User::After(1000 * 50);     // 50 mSec
   561 		User::After(1000 * 50);		// 50 mSec
   559         --timeLeft;
   562 		--timeLeft;
   560         mountState = drive->MountState();
   563 		mountState = drive->MountState();
   561 
   564 
   562         if ((!start && mountState != CMassStorageDrive::EConnected)
   565 		if ((!start && mountState != CMassStorageDrive::EConnected)
   563              ||
   566 			 ||
   564              (start &&
   567 			 (start &&
   565                 (mountState == CMassStorageDrive::EDisconnecting ||
   568 				(mountState == CMassStorageDrive::EDisconnecting || 
   566                 mountState == CMassStorageDrive::EConnected))
   569 				mountState == CMassStorageDrive::EConnected))
   567             )
   570 			)
   568             {
   571 			{
   569             return ETrue;
   572 			return ETrue;
   570             }
   573 			}
   571         } while (timeLeft>0);
   574 		} while (timeLeft>0);
   572 
   575 
   573     //timeout happend
   576 	//timeout happend
   574     iSenseInfo.SetSense(TSenseInfo::ENotReady,
   577 	iSenseInfo.SetSense(TSenseInfo::ENotReady,
   575                         TSenseInfo::EAscLogicalUnitDoesNotRespondToSelection);
   578 						TSenseInfo::EAscLogicalUnitDoesNotRespondToSelection);
   576     return EFalse;
   579 	return EFalse;
   577     }
   580 	}
       
   581 
   578 
   582 
   579 
   583 /**
   580 /**
   584 Command Parser for the PREVENT/ALLOW MEDIA REMOVAL command (0x1E)
   581 Command Parser for the PREVENT/ALLOW MEDIA REMOVAL command (0x1E)
   585 
   582 
   586 @param aData command data (started form position 1)
   583 @param aData command data (started form position 1)
   587 @param aLun Logic unit number 
   584 @param aLun Logic unit number
   588 @return ETrue if successful.
   585 @return ETrue if successful.
   589 */
   586 */
   590 TBool CScsiProtocol::HandlePreventMediaRemoval(TPtrC8& aData, TUint aLun)
   587 TBool CScsiProtocol::HandlePreventMediaRemoval(TPtrC8& aData, TUint aLun)
   591 	{
   588     {
   592 	__FNLOG("CScsiProtocol::HandlePreventMediaRemoval");
   589     OstTrace0(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_PREVENTMEDIAREMOVAL, ">>> PREVENT MEDIA REMOVAL");
   593 	CMassStorageDrive* drive=GetCheckDrive(aLun);
   590     CMassStorageDrive* drive=GetCheckDrive(aLun);
   594 
   591 
   595 	if (drive == NULL)
   592     if (drive == NULL)
   596 		{
   593         {
   597 		return EFalse;
   594         return EFalse;
   598 		}
   595         }
   599 
   596 
   600 	TInt prevent = aData[5] & 0x01;
   597     TInt prevent = aData[5] & 0x01;
   601 	__PRINT1(_L("prevent = %d\n"), prevent);
   598     OstTrace1(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_PREVENTMEDIAREMOVAL1, "    prevent = %d", prevent);
   602 	iDriveManager.SetCritical(aLun, prevent);
   599     iDriveManager.SetCritical(aLun, prevent);
   603 
   600     return ETrue;
   604 	return ETrue;
   601     }
   605 	}
       
   606 
   602 
   607 
   603 
   608 /** Cancel active state, Invoked by transnport when it stops */
   604 /** Cancel active state, Invoked by transnport when it stops */
   609 TInt CScsiProtocol::Cancel()
   605 TInt CScsiProtocol::Cancel()
   610 	{
   606     {
   611 	iDriveManager.SetCritical(CDriveManager::KAllLuns, EFalse);
   607     iDriveManager.SetCritical(CDriveManager::KAllLuns, EFalse);
   612 	return KErrNone;
   608     return KErrNone;
   613 	}
   609     }
   614 
   610 
   615 
   611 
   616 TBool CScsiProtocol::HandleReadFormatCapacities(TUint aLun)
   612 TBool CScsiProtocol::HandleReadFormatCapacities(TUint aLun)
   617 /**
   613 /**
   618  * Command Parser for the READ FORMAT CAPACITIES command (0x23)
   614  * Command Parser for the READ FORMAT CAPACITIES command (0x23)
   619  *
   615  *
   620  * @return ETrue if successful, else a standard Symbian OS error code.
   616  * @return ETrue if successful, else a standard Symbian OS error code.
   621  */
   617  */
   622 	{
   618     {
   623 	__FNLOG("CScsiProtocol::HandleReadFormatCapacities");
   619     OstTrace0(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_READFORMATCAPACITIES, ">>> READ FORMAT CAPACITIES");
   624 
   620     CMassStorageDrive* drive=GetCheckDrive(aLun);
   625 	CMassStorageDrive* drive=GetCheckDrive(aLun);
   621 
   626 
   622     if (drive == NULL)
   627 	if (drive == NULL)
   623         {
   628 		{
   624         return EFalse;
   629 		return EFalse;
   625         }
   630 		}
   626 
   631 
   627     TLocalDriveCapsV4 driveInfo;
   632 	TLocalDriveCapsV4 driveInfo;
   628 
   633 
   629     TInt err = drive->Caps(driveInfo);
   634 	TInt err = drive->Caps(driveInfo);
   630 
   635 
   631     if(err != KErrNone)
   636 	if(err != KErrNone)
   632         {
   637 		{
   633         OstTrace1(TRACE_SMASSSTORAGE, CSCSIPROTOCOL_HANDLEREADFORMATCAPACITIES, "Can't obtain drive Caps. Err=%d", err);
   638 		__PRINT1(_L("Can't obtain drive Caps. Err=%d \n"),err);
   634         iSenseInfo.SetSense(TSenseInfo::ENotReady, TSenseInfo::EMediaNotPresent);
   639 		iSenseInfo.SetSense(TSenseInfo::ENotReady, TSenseInfo::EMediaNotPresent);
   635         return EFalse;
   640 		return EFalse;
   636         }
   641 		}
   637 
   642 
   638     TInt64 driveBlocks = (driveInfo.iDriveAtt & KDriveAttLogicallyRemovable) ? driveInfo.iSize : driveInfo.MediaSizeInBytes();
   643 	TInt64 driveBlocks = (driveInfo.iDriveAtt & KDriveAttLogicallyRemovable) ? driveInfo.iSize : driveInfo.MediaSizeInBytes();
   639     driveBlocks /= MAKE_TINT64(0, KDefaultBlockSize);
   644 	driveBlocks /= MAKE_TINT64(0, KDefaultBlockSize);
   640 
   645 
   641     TPtr8 writeBuf(NULL, 0);
   646 	TPtr8 writeBuf(NULL, 0);
   642     iTransport->GetCommandBufPtr(writeBuf, KReadFormatCapacitiesCommandLength);
   647 	iTransport->GetCommandBufPtr(writeBuf, KReadFormatCapacitiesCommandLength);
   643     writeBuf.FillZ(KReadFormatCapacitiesCommandLength);
   648 	writeBuf.FillZ(KReadFormatCapacitiesCommandLength);
   644 
   649 
   645     writeBuf[3] = 0x08; // Capacity List Length
   650 	writeBuf[3] = 0x08;	// Capacity List Length
   646 
   651 
   647     TUint32 numBlocks = I64LOW(driveBlocks);
   652 	TUint32 numBlocks = I64LOW(driveBlocks);
   648 
   653 
   649     writeBuf[4] = static_cast<TUint8>((numBlocks & 0xFF000000) >> 24);  // Number of blocks
   654 	writeBuf[4] = static_cast<TUint8>((numBlocks & 0xFF000000) >> 24);	// Number of blocks
   650     writeBuf[5] = static_cast<TUint8>((numBlocks & 0x00FF0000) >> 16);  //
   655 	writeBuf[5] = static_cast<TUint8>((numBlocks & 0x00FF0000) >> 16);	//
   651     writeBuf[6] = static_cast<TUint8>((numBlocks & 0x0000FF00) >> 8);   //
   656 	writeBuf[6] = static_cast<TUint8>((numBlocks & 0x0000FF00) >> 8);	//
   652     writeBuf[7] = static_cast<TUint8>((numBlocks & 0x000000FF));        //
   657 	writeBuf[7] = static_cast<TUint8>((numBlocks & 0x000000FF));		//
   653 
   658 
   654     writeBuf[8] = 0x02; // Formatted size
   659 	writeBuf[8] = 0x02;	// Formatted size
   655 
   660 
   656     writeBuf[9]  = 0x00;    // 512 Byte Blocks
   661 	writeBuf[9]  = 0x00;	// 512 Byte Blocks
   657     writeBuf[10] = 0x02;    //
   662 	writeBuf[10] = 0x02;	// 
   658     writeBuf[11] = 0x00;    //
   663 	writeBuf[11] = 0x00;	// 
   659 
   664 
   660     TPtrC8 writeBuf1 = writeBuf;
   665 	TPtrC8 writeBuf1 = writeBuf;
   661 
   666 
   662     iTransport->SetupWriteData(writeBuf1);
   667 	iTransport->SetupWriteData(writeBuf1);
   663 
   668 
   664     return ETrue;
   669 	return ETrue;
   665     }
   670 	}
       
   671 
   666 
   672 
   667 
   673 /**
   668 /**
   674 Command Parser for the READ CAPACITY(10) command (0x25)
   669 Command Parser for the READ CAPACITY(10) command (0x25)
   675 
       
   676 @param aData command data (started form position 1)
       
   677 @param aLun Logic unit number 
       
   678 @return ETrue if successful.
       
   679 */
       
   680 TBool CScsiProtocol::HandleReadCapacity(TPtrC8& aData, TUint aLun)
       
   681 	{
       
   682 	__FNLOG("CScsiProtocol::HandleReadCapacity");
       
   683 	CMassStorageDrive* drive=GetCheckDrive(aLun);
       
   684 
       
   685 	if (drive == NULL)
       
   686 		{
       
   687 		return EFalse;
       
   688 		}
       
   689 
       
   690 	TInt pmi = aData[9] & 0x01;
       
   691 	TInt lba = aData[3] | aData[4] | aData[5] | aData[6];
       
   692 
       
   693 	if (pmi || lba)   //do not support partial medium indicator
       
   694 		{
       
   695 		iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb);
       
   696 		return EFalse;
       
   697 		} 
       
   698 
       
   699 	TLocalDriveCapsV4 driveInfo;
       
   700 
       
   701 	TInt err = drive->Caps(driveInfo);
       
   702 
       
   703 	if(err != KErrNone)
       
   704 		{
       
   705 		__PRINT1(_L("Can't obtain drive Caps. Err=%d \n"),err);
       
   706 		iSenseInfo.SetSense(TSenseInfo::ENotReady, TSenseInfo::EMediaNotPresent);
       
   707 		return EFalse;
       
   708 		}
       
   709 
       
   710 	TInt64 driveBlocks = 0;
       
   711 	if (driveInfo.iDriveAtt & KDriveAttLogicallyRemovable)
       
   712 		{
       
   713 		// Partition Access only 
       
   714 		driveBlocks = driveInfo.iSize / MAKE_TINT64(0, KDefaultBlockSize);
       
   715 		}
       
   716 	else
       
   717 		{
       
   718 		// whole Media Access
       
   719 		driveBlocks = driveInfo.MediaSizeInBytes() / MAKE_TINT64(0, KDefaultBlockSize) - 1;
       
   720 		}
       
   721 	
       
   722 
       
   723 	TPtr8 writeBuf(NULL, 0);
       
   724 	iTransport->GetCommandBufPtr(writeBuf, KReadCapacityCommandLength);
       
   725 	writeBuf.FillZ(KReadCapacityCommandLength);
       
   726 
       
   727 	if (I64HIGH(driveBlocks) == 0)
       
   728 		{
       
   729 		TUint32 numBlocks = I64LOW(driveBlocks);
       
   730 
       
   731 		__PRINT2(_L("Block size=%d, NumBlocks=%d\n"), KDefaultBlockSize, numBlocks);
       
   732 		writeBuf[0] = static_cast<TUint8>((numBlocks & 0xFF000000) >> 24);	// Number of blocks
       
   733 		writeBuf[1] = static_cast<TUint8>((numBlocks & 0x00FF0000) >> 16);
       
   734 		writeBuf[2] = static_cast<TUint8>((numBlocks & 0x0000FF00) >> 8);
       
   735 		writeBuf[3] = static_cast<TUint8>((numBlocks & 0x000000FF));
       
   736 		}
       
   737 	else   
       
   738 		{
       
   739 		writeBuf[0] = writeBuf[1] = writeBuf[2] = writeBuf[3] = 0xFF;  // indicate that size more then )0xFFFFFFFF
       
   740 		}
       
   741 
       
   742 	writeBuf[4] = static_cast<TUint8>((KDefaultBlockSize & 0xFF000000) >> 24);	// Block Size
       
   743 	writeBuf[5] = static_cast<TUint8>((KDefaultBlockSize & 0x00FF0000) >> 16);
       
   744 	writeBuf[6] = static_cast<TUint8>((KDefaultBlockSize & 0x0000FF00) >> 8);
       
   745 	writeBuf[7] = static_cast<TUint8>((KDefaultBlockSize & 0x000000FF));
       
   746 
       
   747 	TPtrC8 writeBuf1 = writeBuf;
       
   748 	iTransport->SetupWriteData(writeBuf1);
       
   749 
       
   750 	return KErrNone;
       
   751 	}
       
   752 
       
   753 
       
   754 /**
       
   755 Command Parser for the READ10 command (0x28)
       
   756 
   670 
   757 @param aData command data (started form position 1)
   671 @param aData command data (started form position 1)
   758 @param aLun Logic unit number
   672 @param aLun Logic unit number
   759 @return ETrue if successful.
   673 @return ETrue if successful.
   760 */
   674 */
   761 TBool CScsiProtocol::HandleRead10(TPtrC8& aData, TUint aLun)
   675 TBool CScsiProtocol::HandleReadCapacity(TPtrC8& aData, TUint aLun)
   762 	{
   676     {
   763 	__FNLOG("CScsiProtocol::HandleRead10");
   677     OstTrace0(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_READCAPACITY, ">>> READ CAPACITY");
   764 	CMassStorageDrive* drive = GetCheckDrive(aLun);
   678     CMassStorageDrive* drive=GetCheckDrive(aLun);
   765 	if (drive == NULL)
   679 
   766 		{
   680     if (drive == NULL)
   767 		return EFalse;
   681         {
   768 		}
   682         return EFalse;
   769 	TInt rdProtect = aData[2] >> 5;
   683         }
   770 	if (rdProtect)
   684 
   771 		{
   685     TInt pmi = aData[9] & 0x01;
   772 		iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb);
   686     TInt lba = aData[3] | aData[4] | aData[5] | aData[6];
   773 		return EFalse;
   687 
   774 		}
   688     if (pmi || lba)   //do not support partial medium indicator
   775 
   689         {
   776 	const TUint32 lba = LBA(aData);
   690         iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb);
   777 	const TUint16 len = LEN(aData);
   691         return EFalse;
   778 
   692         }
   779 	__PRINT2(_L("READ(10) : LBA = 0x%x, Length = %d  (blocks)\n"), lba, len);
   693 
   780 
   694     TLocalDriveCapsV4 driveInfo;
   781 	if (!len)
   695 
   782 		{
   696     TInt err = drive->Caps(driveInfo);
   783 		return ETrue; // do nothing - this is not an error
   697 
   784 		}
   698     if(err != KErrNone)
   785 
   699         {
   786 	TLocalDriveCapsV4 driveInfo;
   700         OstTrace1(TRACE_SMASSSTORAGE, CSCSIPROTOCOL_HANDLEREADCAPACITY1, "ERROR: Can't obtain drive Caps Err=%d", err);
   787 	TInt err = drive->Caps(driveInfo);
   701         iSenseInfo.SetSense(TSenseInfo::ENotReady, TSenseInfo::EMediaNotPresent);
   788 	if (err != KErrNone)
   702         return EFalse;
   789 		{
   703         }
   790 		__PRINT1(_L("Can't obtain drive Caps. Err=%d \n"), err);
   704 
   791 		iSenseInfo.SetSense(TSenseInfo::ENotReady, TSenseInfo::EMediaNotPresent);
   705     TInt64 driveBlocks = 0;
   792 		return EFalse;
   706     if (driveInfo.iDriveAtt & KDriveAttLogicallyRemovable)
   793 		}
   707         {
   794 
   708         // Partition Access only
   795 	const TInt64 bOffset = MAKE_TINT64(0, lba) * KDefaultBlockSize;
   709         driveBlocks = driveInfo.iSize / MAKE_TINT64(0, KDefaultBlockSize);
   796 	const TInt bLength = len * KDefaultBlockSize;
   710         }
   797 	const TInt64 theEnd = bOffset + MAKE_TINT64(0, bLength);
   711     else
   798 	const TInt64 mediaSize = (driveInfo.iDriveAtt & KDriveAttLogicallyRemovable) ? driveInfo.iSize : driveInfo.MediaSizeInBytes() ;
   712         {
   799 	
   713         // whole Media Access
   800 	if (theEnd > mediaSize)  //check if media big enough for this request
   714         driveBlocks = driveInfo.MediaSizeInBytes() / MAKE_TINT64(0, KDefaultBlockSize) - 1;
   801 		{
   715         }
   802 		__PRINT(_L("err - Request ends out of media\n"));
   716 
   803 		iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::ELbaOutOfRange);
   717 
   804 		return EFalse;
   718     TPtr8 writeBuf(NULL, 0);
   805 		}
   719     iTransport->GetCommandBufPtr(writeBuf, KReadCapacityCommandLength);
   806 
   720     writeBuf.FillZ(KReadCapacityCommandLength);
   807 #ifdef MSDC_MULTITHREADED
   721 
   808 	iWriteDriveThread->WaitForWriteEmpty();
   722     if (I64HIGH(driveBlocks) == 0)
   809 
   723         {
   810 	// check if our buffer can hold requested data
   724         TUint32 numBlocks = I64LOW(driveBlocks);
   811 	if (iReadDriveThread->iThreadContext->MaxBufferLength() < bLength)
   725 
   812 		{
   726         OstTraceExt2(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_HANDLEREADCAPACITY2,
   813 		__PRINT(_L("err - Buffer too small\n"));
   727                   "    Block size=0x%x, NumBlocks=0x%x",
   814 		iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb);
   728                   KDefaultBlockSize, numBlocks);
   815 		return EFalse;
   729         writeBuf[0] = static_cast<TUint8>((numBlocks & 0xFF000000) >> 24);  // Number of blocks
   816 		}
   730         writeBuf[1] = static_cast<TUint8>((numBlocks & 0x00FF0000) >> 16);
   817 
   731         writeBuf[2] = static_cast<TUint8>((numBlocks & 0x0000FF00) >> 8);
   818     // Optimisation note : If the host is reading from sectors it just wrote to,
   732         writeBuf[3] = static_cast<TUint8>((numBlocks & 0x000000FF));
   819     // then we have to force a cache-miss so that the real data is read from the
   733         }
   820     // drive. It would be possible to service the read from the write buffers, 
   734     else
   821     // but as the host is probably trying to verify the write data, we don't do 
   735         {
   822     // that for now. 
   736         writeBuf[0] = writeBuf[1] = writeBuf[2] = writeBuf[3] = 0xFF;  // indicate that size more then )0xFFFFFFFF
   823 	if (!iReadDriveThread->ReadDriveData(drive, bOffset, bLength, iWriteDriveThread->IsRecentlyWritten(bOffset,bLength)))
   737         }
   824 		{
   738 
   825 		iSenseInfo.SetSense(TSenseInfo::ENotReady, TSenseInfo::EMediaNotPresent);
   739     writeBuf[4] = static_cast<TUint8>((KDefaultBlockSize & 0xFF000000) >> 24);  // Block Size
   826 		return EFalse;
   740     writeBuf[5] = static_cast<TUint8>((KDefaultBlockSize & 0x00FF0000) >> 16);
   827 		}
   741     writeBuf[6] = static_cast<TUint8>((KDefaultBlockSize & 0x0000FF00) >> 8);
   828 
   742     writeBuf[7] = static_cast<TUint8>((KDefaultBlockSize & 0x000000FF));
   829 	iWriteDriveThread->SetCommandWrite10(EFalse);
   743 
   830 	TBlockDesc* &desc = iReadDriveThread->iThreadContext->iBuffer.iDescReadPtr;
   744     TPtrC8 writeBuf1 = writeBuf;
   831 	TPtrC8 writeBuf1 = desc->iBuf;
   745     iTransport->SetupWriteData(writeBuf1);
   832 #else
   746 
   833 	
   747     return KErrNone;
   834 	TPtr8 writeBuf(NULL, 0);
   748     }
   835 	iTransport->GetReadDataBufPtr(writeBuf);
   749 
   836 	// check if our buffer can hold requested data
   750 
   837 	if (writeBuf.MaxLength() < bLength)
   751 /**
   838 		{
   752 Command Parser for the READ10 command (0x28)
   839 		__PRINT(_L("err - Buffer too small\n"));
       
   840 		iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb);
       
   841 		return EFalse;
       
   842 		}
       
   843 
       
   844 	err = drive->Read(bOffset, bLength, writeBuf, drive->IsWholeMediaAccess());
       
   845 
       
   846 	if (err != KErrNone)
       
   847 		{
       
   848 		__PRINT1(_L("Read failed, err=%d\n"), err);
       
   849 		iSenseInfo.SetSense(TSenseInfo::ENotReady, TSenseInfo::EMediaNotPresent);
       
   850 		return EFalse;
       
   851 		}
       
   852 
       
   853 	TPtrC8 writeBuf1 = writeBuf;
       
   854 #endif // MSDC_MULTITHREADED
       
   855 #ifdef USB_TRANSFER_PUBLISHER
       
   856 	iBytesRead[aLun] += writeBuf1.Length();
       
   857 #endif
       
   858 	iReadTransferPublisher->StartTimer();
       
   859 
       
   860 	// Set up data write to the host
       
   861 	iTransport->SetupWriteData(writeBuf1);
       
   862 
       
   863 	return ETrue;
       
   864 	}
       
   865 
       
   866 
       
   867 /**
       
   868 Command Parser for the WRITE(10) command (0x2A)
       
   869 
   753 
   870 @param aData command data (started form position 1)
   754 @param aData command data (started form position 1)
   871 @param aLun Logic unit number
   755 @param aLun Logic unit number
   872 @return ETrue if successful.
   756 @return ETrue if successful.
   873 */
   757 */
   874 TBool CScsiProtocol::HandleWrite10(TPtrC8& aData, TUint aLun)
   758 TBool CScsiProtocol::HandleRead10(TPtrC8& aData, TUint aLun)
   875 	{
   759     {
   876 	__FNLOG("CScsiProtocol::HandleWrite10");
   760     OstTrace0(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_READ10, ">>> READ(10)");
   877 	CMassStorageDrive* drive = GetCheckDrive(aLun);
   761     CMassStorageDrive* drive = GetCheckDrive(aLun);
   878 	if (drive == NULL)
   762     if (drive == NULL)
   879 		{
   763         {
   880 		return EFalse;
   764         return EFalse;
   881 		}
   765         }
   882 	TInt wrProtect = aData[2] >> 5;
   766     TInt rdProtect = aData[2] >> 5;
   883 	if (wrProtect)
   767     if (rdProtect)
   884 		{
   768         {
   885 		iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb);
   769         iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb);
   886 		return EFalse;
   770         return EFalse;
   887 		}
   771         }
   888 
   772 
   889 	const TUint32 lba = LBA(aData);
   773     const TUint32 lba = LBA(aData);
   890 	const TUint16 len = LEN(aData);
   774     const TUint32 len = LEN(aData);
   891 	__PRINT2(_L("WRITE(10) : LBA = 0x%x, Length = %d (blocks)\n"), lba, len);
   775 
   892 	if (!len)
   776     OstTraceExt2(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_HANDLEREAD10_1,
   893 		{
   777               "    LBA = 0x%x Transfer Len = 0x%x", lba, len);
   894 		return ETrue; // do nothing - this is not an error
   778 
   895 		}
   779     if (!len)
   896 
   780         {
   897 	TLocalDriveCapsV4 driveInfo;
   781         return ETrue; // do nothing - this is not an error
   898 	TInt err = drive->Caps(driveInfo);
   782         }
   899 	if (err != KErrNone)
   783 
   900 		{
   784     TLocalDriveCapsV4 driveInfo;
   901 		__PRINT1(_L("Can't obtain drive Caps. Err=%d \n"), err);
   785     TInt err = drive->Caps(driveInfo);
   902 		iSenseInfo.SetSense(TSenseInfo::ENotReady, TSenseInfo::EMediaNotPresent);
   786     if (err != KErrNone)
   903 		return EFalse;
   787         {
   904 		}
   788         OstTrace1(TRACE_SMASSSTORAGE, CSCSIPROTOCOL_HANDLEREAD10_2, "Can't obtain drive Caps. Err=%d", err);
   905 	if (driveInfo.iMediaAtt & KMediaAttWriteProtected ||
   789         iSenseInfo.SetSense(TSenseInfo::ENotReady, TSenseInfo::EMediaNotPresent);
   906 		driveInfo.iMediaAtt & KMediaAttLocked)
   790         return EFalse;
   907 		{
   791         }
   908 		iSenseInfo.SetSense(TSenseInfo::EDataProtection, TSenseInfo::EWriteProtected);
   792 
   909 		return EFalse;
   793     const TInt64 bOffset = MAKE_TINT64(0, lba) * KDefaultBlockSize;
   910 		}
   794     const TInt bLength = len * KDefaultBlockSize;
   911 
   795     const TInt64 theEnd = bOffset + MAKE_TINT64(0, bLength);
   912 	const TInt64 bOffset = MAKE_TINT64(0, lba) * KDefaultBlockSize;
   796     const TInt64 mediaSize = (driveInfo.iDriveAtt & KDriveAttLogicallyRemovable) ? driveInfo.iSize : driveInfo.MediaSizeInBytes() ;
   913 	iBytesRemain = len * KDefaultBlockSize;
   797 
   914 	const TInt64 theEnd = bOffset + MAKE_TINT64(0, iBytesRemain);
   798     if (theEnd > mediaSize)  //check if media big enough for this request
   915 	const TInt64 mediaSize = (driveInfo.iDriveAtt & KDriveAttLogicallyRemovable) ? driveInfo.iSize : driveInfo.MediaSizeInBytes() ;
   799         {
   916 
   800         OstTrace0(TRACE_SMASSSTORAGE, CSCSIPROTOCOL_HANDLEREAD10_3, "ERROR: Requested size is out of media range");
   917 	if (theEnd > mediaSize)  //check if media big enough for this request
   801         iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::ELbaOutOfRange);
   918 		{
   802         return EFalse;
   919 		__PRINT(_L("err - Request ends out of media\n"));
   803         }
   920 		iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::ELbaOutOfRange);
   804 
   921 		return EFalse;
   805 #ifdef MSDC_MULTITHREADED
   922 		}
   806     iWriteDriveThread->WaitForWriteEmpty();
   923 
   807 
   924 #ifdef MSDC_MULTITHREADED
   808     // check if our buffer can hold requested data
   925 	iWriteDriveThread->SetCommandWrite10(ETrue);
   809     if (iReadDriveThread->iThreadContext->MaxBufferLength() < bLength)
   926 #endif
   810         {
   927 
   811         OstTrace0(TRACE_SMASSSTORAGE, CSCSIPROTOCOL_HANDLEREAD10_4, "ERROR: Buffer too small");
   928 	// Set up the first request for data from the host - either
   812         iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb);
   929 	// KMaxBufSize or the entire transfer length, whichever is smallest.
   813         return EFalse;
   930 	TUint thisLength = (iBytesRemain > KMaxBufSize) ? KMaxBufSize : iBytesRemain;
   814         }
   931 	thisLength = (thisLength > iMediaWriteSize) ? iMediaWriteSize : thisLength;
   815 
   932 
   816     // Optimisation note : If the host is reading from sectors it just wrote to,
   933 	iOffset = bOffset;
   817     // then we have to force a cache-miss so that the real data is read from the
   934 	iLastCommand = EWrite10;
   818     // drive. It would be possible to service the read from the write buffers,
   935 	iLastLun = aLun;
   819     // but as the host is probably trying to verify the write data, we don't do
   936 
   820     // that for now.
   937 	iWriteTransferPublisher->StartTimer();
   821     if (!iReadDriveThread->ReadDriveData(drive, bOffset, bLength, iWriteDriveThread->IsRecentlyWritten(bOffset,bLength)))
   938 	iTransport->SetupReadData(thisLength);
   822         {
   939 
   823         iSenseInfo.SetSense(TSenseInfo::ENotReady, TSenseInfo::EMediaNotPresent);
   940 	return ETrue;
   824         return EFalse;
   941 	}
   825         }
   942 
   826 
   943 
   827     iWriteDriveThread->SetCommandWrite10(EFalse);
   944 /**
   828     TBlockDesc* &desc = iReadDriveThread->iThreadContext->iBuffer.iDescReadPtr;
   945 Command Parser for the VERIFY(10) command (0x2F)
   829     TPtrC8 writeBuf1 = desc->iBuf;
       
   830 #else
       
   831 
       
   832     TPtr8 writeBuf(NULL, 0);
       
   833     iTransport->GetReadDataBufPtr(writeBuf);
       
   834     // check if our buffer can hold requested data
       
   835     if (writeBuf.MaxLength() < bLength)
       
   836         {
       
   837         iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb);
       
   838         return EFalse;
       
   839         }
       
   840 
       
   841     err = drive->Read(bOffset, bLength, writeBuf, drive->IsWholeMediaAccess());
       
   842 
       
   843     if (err != KErrNone)
       
   844         {
       
   845         OstTrace1(TRACE_SMASSSTORAGE, CSCSIPROTOCOL_HANDLEREAD10_5, "ERROR: Read failed err=%d", err);
       
   846         iSenseInfo.SetSense(TSenseInfo::ENotReady, TSenseInfo::EMediaNotPresent);
       
   847         return EFalse;
       
   848         }
       
   849 
       
   850     TPtrC8 writeBuf1 = writeBuf;
       
   851 #endif // MSDC_MULTITHREADED
       
   852 #ifdef USB_TRANSFER_PUBLISHER
       
   853     iBytesRead[aLun] += writeBuf1.Length();
       
   854 #endif
       
   855     iReadTransferPublisher->StartTimer();
       
   856 
       
   857     // Set up data write to the host
       
   858     iTransport->SetupWriteData(writeBuf1);
       
   859 
       
   860     return ETrue;
       
   861     }
       
   862 
       
   863 
       
   864 /**
       
   865 Command Parser for the WRITE(10) command (0x2A)
   946 
   866 
   947 @param aData command data (started form position 1)
   867 @param aData command data (started form position 1)
   948 @param aLun Logic unit number
   868 @param aLun Logic unit number
   949 @return ETrue if successful.
   869 @return ETrue if successful.
   950 */
   870 */
       
   871 TBool CScsiProtocol::HandleWrite10(TPtrC8& aData, TUint aLun)
       
   872     {
       
   873     OstTrace0(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_WRITE10, ">>> WRITE(10)");
       
   874     CMassStorageDrive* drive = GetCheckDrive(aLun);
       
   875     if (drive == NULL)
       
   876         {
       
   877         return EFalse;
       
   878         }
       
   879     TInt wrProtect = aData[2] >> 5;
       
   880     if (wrProtect)
       
   881         {
       
   882         iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb);
       
   883         return EFalse;
       
   884         }
       
   885 
       
   886     const TUint32 lba = LBA(aData);
       
   887     const TUint32 len = LEN(aData);
       
   888     OstTraceExt2(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_HANDLEWRITE10_1, "LBA = 0x%x, Transfer Len = 0x%x", lba, len);
       
   889     if (!len)
       
   890         {
       
   891         return ETrue; // do nothing - this is not an error
       
   892         }
       
   893 
       
   894     TLocalDriveCapsV4 driveInfo;
       
   895     TInt err = drive->Caps(driveInfo);
       
   896     if (err != KErrNone)
       
   897         {
       
   898         OstTrace1(TRACE_SMASSSTORAGE, CSCSIPROTOCOL_WRITE10_2, "ERROR: Can't obtain drive Caps Err=%d", err);
       
   899         iSenseInfo.SetSense(TSenseInfo::ENotReady, TSenseInfo::EMediaNotPresent);
       
   900         return EFalse;
       
   901         }
       
   902     if (driveInfo.iMediaAtt & KMediaAttWriteProtected ||
       
   903         driveInfo.iMediaAtt & KMediaAttLocked)
       
   904         {
       
   905         iSenseInfo.SetSense(TSenseInfo::EDataProtection, TSenseInfo::EWriteProtected);
       
   906         return EFalse;
       
   907         }
       
   908 
       
   909     const TInt64 bOffset = MAKE_TINT64(0, lba) * KDefaultBlockSize;
       
   910     iBytesRemain = len * KDefaultBlockSize;
       
   911     const TInt64 theEnd = bOffset + MAKE_TINT64(0, iBytesRemain);
       
   912     const TInt64 mediaSize = (driveInfo.iDriveAtt & KDriveAttLogicallyRemovable) ? driveInfo.iSize : driveInfo.MediaSizeInBytes() ;
       
   913 
       
   914     if (theEnd > mediaSize)  //check if media big enough for this request
       
   915         {
       
   916         OstTrace0(TRACE_SMASSSTORAGE, CSCSIPROTOCOL_HANDLEWRITE10_3, "Requested size is out of media range");
       
   917         iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::ELbaOutOfRange);
       
   918         return EFalse;
       
   919         }
       
   920 
       
   921 #ifdef MSDC_MULTITHREADED
       
   922     iWriteDriveThread->SetCommandWrite10(ETrue);
       
   923 #endif
       
   924 
       
   925     // Set up the first request for data from the host - either
       
   926     // KMaxBufSize or the entire transfer length, whichever is smallest.
       
   927     TUint thisLength = (iBytesRemain > KMaxBufSize) ? KMaxBufSize : iBytesRemain;
       
   928     thisLength = (thisLength > iMediaWriteSize) ? iMediaWriteSize : thisLength;
       
   929 
       
   930     iOffset = bOffset;
       
   931     iLastCommand = EWrite10;
       
   932     iLastLun = aLun;
       
   933 
       
   934     iWriteTransferPublisher->StartTimer();
       
   935     iTransport->SetupReadData(thisLength);
       
   936 
       
   937     return ETrue;
       
   938     }
       
   939 
       
   940 
       
   941 /**
       
   942 Command Parser for the VERIFY(10) command (0x2F)
       
   943 
       
   944 @param aData command data (started form position 1)
       
   945 @param aLun Logic unit number
       
   946 @return ETrue if successful.
       
   947 */
   951 TBool CScsiProtocol::HandleVerify10(TPtrC8& aData, TUint aLun)
   948 TBool CScsiProtocol::HandleVerify10(TPtrC8& aData, TUint aLun)
   952 	{
   949     {
   953 	__FNLOG("CScsiProtocol::HandleVerify10");
   950     OstTrace0(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_VERIFY10, ">>> VERIFY(10)");
   954 	CMassStorageDrive* drive = GetCheckDrive(aLun);
   951     CMassStorageDrive* drive = GetCheckDrive(aLun);
   955 	if (drive == NULL)
   952     if (drive == NULL)
   956 		{
   953         {
   957 		return EFalse;
   954         return EFalse;
   958 		}
   955         }
   959 
   956 
   960 	TInt vrProtect = aData[2] >> 5;
   957     TInt vrProtect = aData[2] >> 5;
   961 	if (vrProtect)
   958     if (vrProtect)
   962 		{
   959         {
   963 		iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb);
   960         iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb);
   964 		return EFalse;
   961         return EFalse;
   965 		}
   962         }
   966 
   963 
   967 	const TUint32 lba = LBA(aData);
   964     const TUint32 lba = LBA(aData);
   968 	const TUint16 len = LEN(aData);
   965     const TUint32 len = LEN(aData);
   969 	__PRINT2(_L("VERIFY(10) : LBA = %d, Length = %d  (blocks)\n"), lba, len);
   966     OstTraceExt2(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_VERIFY10_1, "VERIFY(10) : LBA = 0x%x Transfer Len = 0x%x", lba, len);
   970 
   967 
   971 	TInt bytChk = aData[2] & 0x02;
   968     TInt bytChk = aData[2] & 0x02;
   972 	if (!len)
   969     if (!len)
   973 		{
   970         {
   974 		return ETrue; // do nothing - this is not an error
   971         return ETrue; // do nothing - this is not an error
   975 		}
   972         }
   976 
   973 
   977 	TLocalDriveCapsV4 driveInfo;
   974     TLocalDriveCapsV4 driveInfo;
   978 	TInt err = drive->Caps(driveInfo);
   975     TInt err = drive->Caps(driveInfo);
   979 	if (err != KErrNone)
   976     if (err != KErrNone)
   980 		{
   977         {
   981 		__PRINT1(_L("Can't obtain drive Caps. Err=%d \n"), err);
   978         OstTrace1(TRACE_SMASSSTORAGE, CSCSIPROTOCOL_VERIFY10_2, "ERROR: Can't obtain drive Caps Err=%d", err);
   982 		iSenseInfo.SetSense(TSenseInfo::ENotReady, TSenseInfo::EMediaNotPresent);
   979         iSenseInfo.SetSense(TSenseInfo::ENotReady, TSenseInfo::EMediaNotPresent);
   983 		return EFalse;
   980         return EFalse;
   984 		}
   981         }
   985 
   982 
   986 	const TInt64 bOffset = MAKE_TINT64(0, lba) * KDefaultBlockSize;
   983     const TInt64 bOffset = MAKE_TINT64(0, lba) * KDefaultBlockSize;
   987 	const TInt bLength = len * KDefaultBlockSize;
   984     const TInt bLength = len * KDefaultBlockSize;
   988 	const TInt64 theEnd = bOffset + MAKE_TINT64(0, bLength);
   985     const TInt64 theEnd = bOffset + MAKE_TINT64(0, bLength);
   989 	const TInt64 mediaSize = (driveInfo.iDriveAtt & KDriveAttLogicallyRemovable) ? driveInfo.iSize : driveInfo.MediaSizeInBytes() ;
   986     const TInt64 mediaSize = (driveInfo.iDriveAtt & KDriveAttLogicallyRemovable) ? driveInfo.iSize : driveInfo.MediaSizeInBytes() ;
   990 
   987 
   991 	// check if media big enough for this request
   988     // check if media big enough for this request
   992 	if (theEnd > mediaSize)
   989     if (theEnd > mediaSize)
   993 		{
   990         {
   994 		iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::ELbaOutOfRange);
   991         iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::ELbaOutOfRange);
   995 		return EFalse;
   992         return EFalse;
   996 		}
   993         }
   997 
   994 
   998 	// check if our buffer can hold requested data
   995     // check if our buffer can hold requested data
   999 #ifdef MSDC_MULTITHREADED
   996 #ifdef MSDC_MULTITHREADED
  1000 	if (iWriteDriveThread->iThreadContext->MaxBufferLength() < bLength)
   997     if (iWriteDriveThread->iThreadContext->MaxBufferLength() < bLength)
  1001 #else
   998 #else
  1002 	TPtr8 writeBuf(NULL, 0);
   999     TPtr8 writeBuf(NULL, 0);
  1003 	iTransport->GetReadDataBufPtr(writeBuf);
  1000     iTransport->GetReadDataBufPtr(writeBuf);
  1004 	if (writeBuf.MaxLength() < bLength)
  1001     if (writeBuf.MaxLength() < bLength)
  1005 #endif
  1002 #endif
  1006 		{
  1003         {
  1007 		iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb);
  1004         iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb);
  1008 		return EFalse;
  1005         return EFalse;
  1009 		}
  1006         }
  1010 
  1007 
  1011 	if (!bytChk)
  1008     if (!bytChk)
  1012 		{
  1009         {
  1013 		// BYTCHK==0 : Perform a medium verification with no data comparison and not transfer any data from the application client data-out buffer.
  1010         // BYTCHK==0 : Perform a medium verification with no data comparison and not transfer any data from the application client data-out buffer.
  1014 		// The device should attempt to read from the specified locations
  1011         // The device should attempt to read from the specified locations
  1015 #ifdef MSDC_MULTITHREADED
  1012 #ifdef MSDC_MULTITHREADED
  1016 		TPtr8 writeBuf = iWriteDriveThread->iThreadContext->GetReadBuffer(bLength);
  1013         TPtr8 writeBuf = iWriteDriveThread->iThreadContext->GetReadBuffer(bLength);
  1017 #else
  1014 #else
  1018 		writeBuf.SetLength(bLength);
  1015         writeBuf.SetLength(bLength);
  1019 #endif
  1016 #endif
  1020 		err = drive->Read(bOffset, bLength, writeBuf, drive->IsWholeMediaAccess());
  1017         err = drive->Read(bOffset, bLength, writeBuf, drive->IsWholeMediaAccess());
  1021 		if (err != KErrNone)
  1018         if (err != KErrNone)
  1022 			{
  1019             {
  1023 			iSenseInfo.SetSense(TSenseInfo::EMisCompare);
  1020             iSenseInfo.SetSense(TSenseInfo::EMisCompare);
  1024 			return EFalse;
  1021             return EFalse;
  1025 			}
  1022             }
  1026 		return ETrue;
  1023         return ETrue;
  1027 		}
  1024         }
  1028 
  1025 
  1029 	// BYTCHK==1 : perform a byte-by-byte comparison of user data read from the medium & user data transferred from the application client data-out buffer.
  1026     // BYTCHK==1 : perform a byte-by-byte comparison of user data read from the medium & user data transferred from the application client data-out buffer.
  1030 	// The host sends data in the data-transport phase, and the device should verify that the received data matches what is stored in the device.
  1027     // The host sends data in the data-transport phase, and the device should verify that the received data matches what is stored in the device.
  1031 
  1028 
  1032 	iOffset = bOffset;
  1029     iOffset = bOffset;
  1033 	iLastCommand = EVerify10;
  1030     iLastCommand = EVerify10;
  1034 	iLastLun = aLun;
  1031     iLastLun = aLun;
  1035 
  1032 
  1036 	iTransport->SetupReadData(bLength);
  1033     iTransport->SetupReadData(bLength);
  1037 
  1034 
  1038 	return ETrue;
  1035     return ETrue;
  1039 	}
  1036     }
  1040 
  1037 
  1041 
  1038 
  1042 /**
  1039 /**
  1043 Called by the transport when the requested data has been read or an error has
  1040 Called by the transport when the requested data has been read or an error has
  1044 occurred during the read.
  1041 occurred during the read.
  1049         the transfer immediately, KErrNotReady if insufficient data is
  1046         the transfer immediately, KErrNotReady if insufficient data is
  1050         available in the buffer so the transport should wait for it to arrive,
  1047         available in the buffer so the transport should wait for it to arrive,
  1051         KErrNone if command processing is complete and was successful.
  1048         KErrNone if command processing is complete and was successful.
  1052 */
  1049 */
  1053 TInt CScsiProtocol::ReadComplete(TInt aError)
  1050 TInt CScsiProtocol::ReadComplete(TInt aError)
  1054 	{
  1051     {
  1055 	__FNLOG("CScsiProtocol::ReadComplete");
  1052     OstTrace1(TRACE_SMASSSTORAGE_MEDIA, CSCSIPROTOCOL_READCOMPLETE0, "ReadComplete = 0x%X", aError);
  1056 	__PRINT1(_L("Error = 0x%X \n"), aError);
  1053     const TInt64 bOffset = iOffset;
  1057 	const TInt64 bOffset = iOffset;
  1054     TUint8 lastCommand = iLastCommand;
  1058 	TUint8 lastCommand = iLastCommand;
  1055     TUint lastLun = iLastLun;
  1059 	TUint lastLun = iLastLun;
  1056 
  1060 
  1057     iOffset = 0;
  1061 	iOffset = 0;
  1058     iLastCommand = EUndefinedCommand;
  1062 	iLastCommand = EUndefinedCommand;
  1059     iLastLun = KUndefinedLun;
  1063 	iLastLun = KUndefinedLun;
  1060 
  1064 
  1061 //  OstTrace1(TRACE_SMASSSTORAGE_MEDIA, CSCSIPROTOCOL_READCOMPLETE1, "lastCommand = d", lastCommand);
  1065 	__PRINT1(_L("Last command was: %s\n"),
  1062 
  1066 			 (lastCommand == EUndefinedCommand) ? _S("Undefined") :
  1063     if (aError != KErrNone ||
  1067 			 ((lastCommand == EWrite10) ? _S("EWrite10") :
  1064         lastCommand == EUndefinedCommand ||
  1068 			  ((lastCommand == EVerify10) ? _S("EVerify10") :
  1065         lastLun == KUndefinedLun)
  1069 			   _S("Unknown"))));
  1066         {
  1070 
  1067         iSenseInfo.SetSense(TSenseInfo::EAbortedCommand);
  1071 	if (aError != KErrNone ||
  1068         return KErrAbort;
  1072 		lastCommand == EUndefinedCommand ||
  1069         }
  1073 		lastLun == KUndefinedLun)
  1070 
  1074 		{
  1071     CMassStorageDrive* drive = GetCheckDrive(lastLun);
  1075 		iSenseInfo.SetSense(TSenseInfo::EAbortedCommand);
  1072     if (drive == NULL)
  1076 		return KErrAbort;
  1073         {
  1077 		}
  1074         return KErrAbort;
  1078 
  1075         }
  1079 	CMassStorageDrive* drive = GetCheckDrive(lastLun);
  1076 
  1080 	if (drive == NULL)
  1077     if (lastCommand == EWrite10)
  1081 		{
  1078         {
  1082 		return KErrAbort;
  1079         TPtrC8 writeBuf(NULL, 0);
  1083 		}
  1080         iTransport->GetWriteDataBufPtr(writeBuf);
  1084 
  1081 
  1085 	if (lastCommand == EWrite10)
       
  1086 		{
       
  1087 		TPtrC8 writeBuf(NULL, 0);
       
  1088 		iTransport->GetWriteDataBufPtr(writeBuf);
       
  1089 		
       
  1090 #ifdef USB_TRANSFER_PUBLISHER
  1082 #ifdef USB_TRANSFER_PUBLISHER
  1091 	iBytesWritten[lastLun] += writeBuf.Length();
  1083     iBytesWritten[lastLun] += writeBuf.Length();
  1092 #endif
  1084 #endif
  1093 
  1085 
  1094 #ifdef MSDC_MULTITHREADED
  1086 #ifdef MSDC_MULTITHREADED
  1095 		TInt err = iWriteDriveThread->WriteDriveData(drive, bOffset, writeBuf, ProcessWriteComplete, this);
  1087         TInt err = iWriteDriveThread->WriteDriveData(drive, bOffset, writeBuf, ProcessWriteComplete, this);
  1096 
  1088 
  1097 		if (err != KErrNone)
  1089         if (err != KErrNone)
  1098 			{
  1090             {
  1099 			iDeferredSenseInfo.SetSense(TSenseInfo::EMediumError);
  1091             iDeferredSenseInfo.SetSense(TSenseInfo::EMediumError);
  1100 			}
  1092             }
  1101 
  1093 
  1102 		TUint thisLength = iWriteDriveThread->WriteBufferLength();
  1094         TUint thisLength = iWriteDriveThread->WriteBufferLength();
  1103 #else
  1095 #else
  1104 #ifdef MEASURE_AND_DISPLAY_WRITE_TIME
  1096         OstTrace1(TRACE_SMASSSTORAGE_MEDIA, CSCSIPROTOCOL_READCOMPLETE2, "SCSI: writing 0x%x bytes", writeBuf.Length());
  1105 		RDebug::Print(_L("SCSI: writing %d bytes\n"), writeBuf.Length());
  1097         TInt err = drive->Write(bOffset, writeBuf, drive->IsWholeMediaAccess());
  1106 		TTime t0, t1;
  1098         if (err != KErrNone)
  1107 		t0.HomeTime();
  1099             {
       
  1100             OstTrace1(TRACE_SMASSSTORAGE_MEDIA, CSCSIPROTOCOL_READCOMPLETE3, "Error after write = 0x%x", err);
       
  1101             iSenseInfo.SetSense(TSenseInfo::EAbortedCommand);
       
  1102             return KErrAbort;
       
  1103             }
       
  1104 
       
  1105         TUint thisLength = writeBuf.Length();
       
  1106 #endif // MSDC_MULTITHREADED
       
  1107         iOffset = bOffset + MAKE_TINT64(0, thisLength);
       
  1108         iBytesRemain -= thisLength;
       
  1109         if ((TInt)iBytesRemain > 0)
       
  1110             {
       
  1111             // More data is expected - set up another request to read from the host
       
  1112             iLastCommand = EWrite10;
       
  1113             iLastLun = lastLun;
       
  1114 
       
  1115             TUint minLength = (iBytesRemain < iMediaWriteSize) ? iBytesRemain : iMediaWriteSize;
       
  1116             TUint bytesAvail = iTransport->BytesAvailable() & ~(KDefaultBlockSize-1);
       
  1117 
       
  1118             TBool wait = EFalse;
       
  1119             thisLength = bytesAvail ? bytesAvail : minLength;
       
  1120             if (thisLength < minLength)
       
  1121                 {
       
  1122                 // Not enough data is available at the transport to satisfy the request,
       
  1123                 // so return KErrNotReady to indicate that the transport should wait.
       
  1124                 thisLength = minLength;
       
  1125                 wait = ETrue;
       
  1126                 }
       
  1127 
       
  1128             thisLength = (thisLength > KMaxBufSize) ? KMaxBufSize : thisLength;
       
  1129 
       
  1130             iTransport->SetupReadData(thisLength);
       
  1131 
       
  1132             return wait ? KErrNotReady : KErrCompletion;
       
  1133             }
       
  1134         }
       
  1135     else if (lastCommand == EVerify10)
       
  1136         {
       
  1137         HBufC8* hostData = NULL;
       
  1138         TPtrC8 writeBuf(NULL, 0);
       
  1139         iTransport->GetWriteDataBufPtr(writeBuf);
       
  1140 #ifdef MSDC_MULTITHREADED
       
  1141         TRAPD(err, hostData = HBufC8::NewL(writeBuf.Length()));
  1108 #else
  1142 #else
  1109 		__PRINT1(_L("SCSI: writing %d bytes\n"), writeBuf.Length());
  1143         TRAPD(err, hostData = HBufC8::NewL(writeBuf.Length()));
  1110 #endif
  1144 #endif
  1111 
  1145         if (err != KErrNone || hostData == NULL)
  1112 #ifdef INJECT_ERROR
  1146             {
  1113 		if (writeBuf[0] == '2')
  1147             iSenseInfo.SetSense(TSenseInfo::EAbortedCommand, TSenseInfo::EInsufficientRes);
  1114 		{
  1148             return KErrAbort;
  1115 			writeBuf[0] = 'x';
  1149             }
  1116 			RDebug::Printf("Injecting error");
  1150 
  1117 		}
  1151 #ifdef MSDC_MULTITHREADED
  1118 
  1152         // copy the data
  1119 		RDebug::Printf("%08lx %x [%x] [%x]", bOffset,writeBuf.Length(), 
  1153         *hostData = writeBuf;
  1120 			writeBuf[0],
  1154         TPtr8 readBuf = iWriteDriveThread->iThreadContext->GetReadBuffer();
  1121 			writeBuf[writeBuf.Length()-1]);
  1155         err = drive->Read(bOffset, writeBuf.Length(), readBuf, drive->IsWholeMediaAccess());
  1122 #endif
  1156         if (err == KErrNone)
  1123 		
  1157             {
  1124 		TInt err = drive->Write(bOffset, writeBuf, drive->IsWholeMediaAccess());
  1158             err = (hostData->Compare(readBuf) == 0) ? KErrNone : KErrCorrupt;
  1125 
  1159             }
  1126 #ifdef INJECT_ERROR
       
  1127 		if (writeBuf[0] == 'x')
       
  1128 		{
       
  1129 			err = KErrUnknown;
       
  1130 		}
       
  1131 #endif
       
  1132 
       
  1133 #ifdef MEASURE_AND_DISPLAY_WRITE_TIME
       
  1134 		t1.HomeTime();
       
  1135 		const TTimeIntervalMicroSeconds time = t1.MicroSecondsFrom(t0);
       
  1136 		const TUint time_ms = I64LOW(time.Int64() / 1000);
       
  1137 		RDebug::Print(_L("SCSI: write took %d ms\n"), time_ms);
       
  1138 #endif
       
  1139 		if (err != KErrNone)
       
  1140 			{
       
  1141 			__PRINT1(_L("Error after write = 0x%X \n"), err);
       
  1142 			iSenseInfo.SetSense(TSenseInfo::EAbortedCommand);
       
  1143 			return KErrAbort;
       
  1144 			}
       
  1145 
       
  1146 		TUint thisLength = writeBuf.Length();
       
  1147 #endif // MSDC_MULTITHREADED
       
  1148 		iOffset = bOffset + MAKE_TINT64(0, thisLength);
       
  1149 		iBytesRemain -= thisLength;
       
  1150 		if ((TInt)iBytesRemain > 0)
       
  1151 			{
       
  1152 			// More data is expected - set up another request to read from the host
       
  1153 			iLastCommand = EWrite10;
       
  1154 			iLastLun = lastLun;
       
  1155 
       
  1156 			TUint minLength = (iBytesRemain < iMediaWriteSize) ? iBytesRemain : iMediaWriteSize;
       
  1157 			TUint bytesAvail = iTransport->BytesAvailable() & ~(KDefaultBlockSize-1);
       
  1158 
       
  1159 			TBool wait = EFalse;
       
  1160 			thisLength = bytesAvail ? bytesAvail : minLength;
       
  1161 			if (thisLength < minLength)
       
  1162 				{
       
  1163 				// Not enough data is available at the transport to satisfy the request,
       
  1164 				// so return KErrNotReady to indicate that the transport should wait.
       
  1165 				thisLength = minLength;
       
  1166 				wait = ETrue;
       
  1167 				}
       
  1168 
       
  1169 			thisLength = (thisLength > KMaxBufSize) ? KMaxBufSize : thisLength;
       
  1170 
       
  1171 			iTransport->SetupReadData(thisLength);
       
  1172 
       
  1173 			return wait ? KErrNotReady : KErrCompletion;
       
  1174 			}
       
  1175 		}
       
  1176 	else if (lastCommand == EVerify10)
       
  1177 		{
       
  1178 		HBufC8* hostData = NULL;
       
  1179 		TPtrC8 writeBuf(NULL, 0);
       
  1180 		iTransport->GetWriteDataBufPtr(writeBuf);
       
  1181 #ifdef MSDC_MULTITHREADED
       
  1182 		TRAPD(err, hostData = HBufC8::NewL(writeBuf.Length()));
       
  1183 #else
  1160 #else
  1184 		TRAPD(err, hostData = HBufC8::NewL(writeBuf.Length()));
  1161         *hostData = writeBuf;
  1185 #endif
  1162         TPtr8 readBuf((TUint8*) writeBuf.Ptr(), writeBuf.Length());
  1186 		if (err != KErrNone || hostData == NULL)
  1163         err = drive->Read(bOffset, writeBuf.Length(), readBuf, drive->IsWholeMediaAccess());
  1187 			{
  1164         if (err == KErrNone)
  1188 			iSenseInfo.SetSense(TSenseInfo::EAbortedCommand, TSenseInfo::EInsufficientRes);
  1165             {
  1189 			return KErrAbort;
  1166             err = (hostData->Compare(readBuf) == 0) ? KErrNone : KErrCorrupt;
  1190 			}
  1167             }
  1191 
  1168 #endif
  1192 #ifdef MSDC_MULTITHREADED
  1169 
  1193 		// copy the data
  1170         if (err != KErrNone)
  1194 		*hostData = writeBuf;
  1171             {
  1195 		TPtr8 readBuf = iWriteDriveThread->iThreadContext->GetReadBuffer(); 
  1172             iSenseInfo.SetSense(TSenseInfo::EMisCompare);
  1196 		err = drive->Read(bOffset, writeBuf.Length(), readBuf, drive->IsWholeMediaAccess());
  1173             }
  1197 		if (err == KErrNone)
  1174 
  1198 			{
  1175         delete hostData;
  1199 			err = (hostData->Compare(readBuf) == 0) ? KErrNone : KErrCorrupt;
  1176         }
  1200 			}
  1177     else // unknown command
  1201 #else
  1178         {
  1202 		*hostData = writeBuf;
  1179         iSenseInfo.SetSense(TSenseInfo::EAbortedCommand);
  1203 		TPtr8 readBuf((TUint8*) writeBuf.Ptr(), writeBuf.Length()); 
  1180         }
  1204 		err = drive->Read(bOffset, writeBuf.Length(), readBuf, drive->IsWholeMediaAccess());
  1181     return iSenseInfo.SenseOk() ? KErrNone : KErrAbort;
  1205 		if (err == KErrNone)
  1182     }
  1206 			{
       
  1207 			err = (hostData->Compare(readBuf) == 0) ? KErrNone : KErrCorrupt;
       
  1208 			}
       
  1209 #endif
       
  1210 
       
  1211 		if (err != KErrNone)
       
  1212 			{
       
  1213 			iSenseInfo.SetSense(TSenseInfo::EMisCompare);
       
  1214 			}
       
  1215 
       
  1216 		delete hostData;
       
  1217 		}
       
  1218 	else // unknown command
       
  1219 		{
       
  1220 		iSenseInfo.SetSense(TSenseInfo::EAbortedCommand);
       
  1221 		}
       
  1222 	return iSenseInfo.SenseOk() ? KErrNone : KErrAbort;
       
  1223 	}
       
  1224 
  1183 
  1225 
  1184 
  1226 /**
  1185 /**
  1227 Command Parser for the MODE SENSE(06) command (0x1A)
  1186 Command Parser for the MODE SENSE(06) command (0x1A)
  1228 
  1187 
  1229 @return ETrue if successful.
  1188 @return ETrue if successful.
  1230 */
  1189 */
  1231 TBool CScsiProtocol::HandleModeSense6(TPtrC8& aData, TUint aLun)
  1190 TBool CScsiProtocol::HandleModeSense6(TPtrC8& aData, TUint aLun)
  1232 	{
  1191     {
  1233 	__FNLOG("CScsiProtocol::HandleModeSense6");
  1192     OstTrace0(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_MODESENSE6, ">>> MODESENSE(06)");
  1234 
  1193     TInt pageCode = aData[3] & 0x3F;
  1235 	TInt pageCode = aData[3] & 0x3F;
  1194     TUint8 pageControl= static_cast<TUint8>(aData[3] >>6);
  1236 	TUint8 pageControl= static_cast<TUint8>(aData[3] >>6);
  1195 
  1237 
  1196     if (pageCode != KAllPages || pageControl == KChangeableValues)
  1238 	if (pageCode != KAllPages || pageControl == KChangeableValues) 
  1197         {
  1239 		{
  1198         iSenseInfo.SetSense(TSenseInfo::EIllegalRequest,TSenseInfo::EInvalidFieldInCdb);
  1240 		__PRINT(_L("TSenseInfo::EIllegalRequest,TSenseInfo::EInvalidFieldInCdb"));
  1199         return EFalse;
  1241 		iSenseInfo.SetSense(TSenseInfo::EIllegalRequest,TSenseInfo::EInvalidFieldInCdb);
  1200         }
  1242 		return EFalse;
  1201 
  1243 		}
  1202     // reserve 4 bytes for Length, Media type, Device-specific parameter and Block descriptor length
  1244 
  1203     TPtr8 writeBuf(NULL, 0);
  1245 	// reserve 4 bytes for Length, Media type, Device-specific parameter and Block descriptor length
  1204     iTransport->GetCommandBufPtr(writeBuf, KModeSense6CommandLength);
  1246 	TPtr8 writeBuf(NULL, 0);
  1205     writeBuf.FillZ(KModeSense6CommandLength);
  1247 	iTransport->GetCommandBufPtr(writeBuf, KModeSense6CommandLength);
  1206 
  1248 	writeBuf.FillZ(KModeSense6CommandLength);
  1207     if (pageControl != KDefaultValues)
  1249 
  1208         {
  1250 	if (pageControl != KDefaultValues)
  1209         //check if drive write protected
  1251 		{
  1210         CMassStorageDrive* drive=GetCheckDrive(aLun);
  1252 		//check if drive write protected
  1211         if (drive == NULL)
  1253 		CMassStorageDrive* drive=GetCheckDrive(aLun);
  1212             {
  1254 		if (drive == NULL)
  1213             OstTrace0(TRACE_SMASSSTORAGE, CSCSIPROTOCOL_HANDLEMODESENSE6_1, "drive == null");
  1255 			{
  1214             return EFalse;
  1256 			__PRINT(_L("drive == null"));
  1215             }
  1257 			return EFalse;
  1216 
  1258 			}
  1217         TLocalDriveCapsV4 driveInfo;
  1259 
  1218         TInt err = drive->Caps(driveInfo);
  1260 		TLocalDriveCapsV4 driveInfo;
  1219         if (err != KErrNone)
  1261 		TInt err = drive->Caps(driveInfo);
  1220             {
  1262 		if (err != KErrNone)
  1221             OstTrace1(TRACE_SMASSSTORAGE, CSCSIPROTOCOL_MODESENSE6_2, "ERROR: Can't obtain drive Caps Err=%d", err);
  1263 			{
  1222             iSenseInfo.SetSense(TSenseInfo::ENotReady, TSenseInfo::EMediaNotPresent);
  1264 			__PRINT(_L("TSenseInfo::ENotReady"));
  1223             return EFalse ;
  1265 			iSenseInfo.SetSense(TSenseInfo::ENotReady, TSenseInfo::EMediaNotPresent);
  1224             }
  1266 			return EFalse ;
  1225 
  1267 			}
  1226         if (driveInfo.iMediaAtt & KMediaAttWriteProtected)
  1268 
  1227             {
  1269 		if (driveInfo.iMediaAtt & KMediaAttWriteProtected)
  1228             writeBuf[2] = 1<<7;  // set SWP bit at the Device Specific parameters
  1270 			{
  1229             }
  1271 			writeBuf[2] = 1<<7;  // set SWP bit at the Device Specific parameters
  1230         }
  1272 			}
  1231 
  1273 		}
  1232     writeBuf[0]=3;  //Sending only Mode parameter header
  1274 
  1233 
  1275 	writeBuf[0]=3;  //Sending only Mode parameter header
  1234     TPtrC8 writeBuf1 = writeBuf;
  1276 
  1235 
  1277 	TPtrC8 writeBuf1 = writeBuf;
  1236     iTransport->SetupWriteData(writeBuf1);
  1278 
  1237 
  1279 	iTransport->SetupWriteData(writeBuf1);
  1238     return (iSenseInfo.SenseOk());
  1280 
  1239     }
  1281 	return (iSenseInfo.SenseOk());
       
  1282 	}
       
  1283 
  1240 
  1284 
  1241 
  1285 /**
  1242 /**
  1286 Command Parser for the MODE SENSE(10) command (0x5A)
  1243 Command Parser for the MODE SENSE(10) command (0x5A)
  1287 
  1244 
  1288 @return ETrue if successful.
  1245 @return ETrue if successful.
  1289 */
  1246 */
  1290 TBool CScsiProtocol::HandleModeSense10(TPtrC8& aData, TUint aLun)
  1247 TBool CScsiProtocol::HandleModeSense10(TPtrC8& aData, TUint aLun)
  1291 	{
  1248     {
  1292 	__FNLOG("CScsiProtocol::HandleModeSense10");
  1249     OstTrace0(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_MODESENSE10, ">>> MODESENSE(10)");
  1293 
  1250     TInt pageCode = aData[3] & 0x3F;
  1294 	TInt pageCode = aData[3] & 0x3F;
  1251     TUint8 pageControl= static_cast<TUint8>(aData[3] >>6);
  1295 	TUint8 pageControl= static_cast<TUint8>(aData[3] >>6);
  1252 
  1296 
  1253     if (pageCode != KAllPages || pageControl == KChangeableValues)
  1297 	if (pageCode != KAllPages || pageControl == KChangeableValues) 
  1254         {
  1298 		{
  1255         iSenseInfo.SetSense(TSenseInfo::EIllegalRequest,TSenseInfo::EInvalidFieldInCdb);
  1299 		__PRINT(_L("TSenseInfo::EIllegalRequest,TSenseInfo::EInvalidFieldInCdb"));
  1256         return EFalse;
  1300 		iSenseInfo.SetSense(TSenseInfo::EIllegalRequest,TSenseInfo::EInvalidFieldInCdb);
  1257         }
  1301 		return EFalse;
  1258 
  1302 		}
  1259     // reserve 8 bytes for Length, Media type, Device-specific parameter and Block descriptor length
  1303 
  1260     TPtr8 writeBuf(NULL, 0);
  1304 	// reserve 8 bytes for Length, Media type, Device-specific parameter and Block descriptor length
  1261     iTransport->GetCommandBufPtr(writeBuf, KModeSense10CommandLength);
  1305 	TPtr8 writeBuf(NULL, 0);
  1262     writeBuf.FillZ(KModeSense10CommandLength);
  1306 	iTransport->GetCommandBufPtr(writeBuf, KModeSense10CommandLength);
  1263 
  1307 	writeBuf.FillZ(KModeSense10CommandLength);
  1264     if (pageControl != KDefaultValues)
  1308 
  1265         {
  1309 	if (pageControl != KDefaultValues)
  1266         //check if drive write protected
  1310 		{
  1267         CMassStorageDrive* drive=GetCheckDrive(aLun);
  1311 		//check if drive write protected
  1268         if (drive == NULL)
  1312 		CMassStorageDrive* drive=GetCheckDrive(aLun);
  1269             {
  1313 		if (drive == NULL)
  1270             OstTrace0(TRACE_SMASSSTORAGE, CSCSIPROTOCOL_HANDLEMODESENSE10_1, "drive == null");
  1314 			{
  1271             return EFalse;
  1315 			__PRINT(_L("drive == null"));
  1272             }
  1316 			return EFalse;
  1273 
  1317 			}
  1274         TLocalDriveCapsV4 driveInfo;
  1318 
  1275         TInt err = drive->Caps(driveInfo);
  1319 		TLocalDriveCapsV4 driveInfo;
  1276         if (err != KErrNone)
  1320 		TInt err = drive->Caps(driveInfo);
  1277             {
  1321 		if (err != KErrNone)
  1278             OstTrace1(TRACE_SMASSSTORAGE, CSCSIPROTOCOL_MODESENSE10_1, "ERROR: Can't obtain drive Caps Err=%d", err);
  1322 			{
  1279             iSenseInfo.SetSense(TSenseInfo::ENotReady, TSenseInfo::EMediaNotPresent);
  1323 			__PRINT(_L("TSenseInfo::ENotReady"));
  1280             return EFalse ;
  1324 			iSenseInfo.SetSense(TSenseInfo::ENotReady, TSenseInfo::EMediaNotPresent);
  1281             }
  1325 			return EFalse ;
  1282 
  1326 			}
  1283         if (driveInfo.iMediaAtt & KMediaAttWriteProtected)
  1327 
  1284             {
  1328 		if (driveInfo.iMediaAtt & KMediaAttWriteProtected)
  1285             writeBuf[3] = 1<<7;  // set SWP bit at the Device Specific parameters
  1329 			{
  1286             }
  1330 			writeBuf[3] = 1<<7;  // set SWP bit at the Device Specific parameters
  1287         }
  1331 			}
  1288 
  1332 		}
  1289     writeBuf[1]=6;  //Sending only Mode parameter header
  1333 
  1290 
  1334 	writeBuf[1]=6;  //Sending only Mode parameter header
  1291     TPtrC8 writeBuf1 = writeBuf;
  1335 
  1292 
  1336 	TPtrC8 writeBuf1 = writeBuf;
  1293     iTransport->SetupWriteData(writeBuf1);
  1337 
  1294 
  1338 	iTransport->SetupWriteData(writeBuf1);
  1295     return (iSenseInfo.SenseOk());
  1339 
  1296     }
  1340 	return (iSenseInfo.SenseOk());
  1297 
  1341 	}
  1298 
  1342 
  1299 
  1343 
       
  1344