kerneltest/f32test/shostmassstorage/testclient/usbtestmsclient/protocol/cscsiserverprotocol.cpp
changeset 0 a41df078684a
child 297 b2826f67641f
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     1 // Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of the License "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include <e32base.h>
       
    17 #include <f32file.h>
       
    18 #include <e32property.h>
       
    19 
       
    20 #include "mstypes.h"
       
    21 #include "msctypes.h"
       
    22 #include "usbmsshared.h"
       
    23 
       
    24 #include "drivemanager.h"
       
    25 #include "drivepublisher.h"
       
    26 #include "tscsiserverreq.h"
       
    27 #include "tscsiservercmds.h"
       
    28 #include "mserverprotocol.h"
       
    29 #include "mdevicetransport.h"
       
    30 
       
    31 #include "testman.h"
       
    32 #include "cscsiserverprotocol.h"
       
    33 #include "debug.h"
       
    34 #include "msdebug.h"
       
    35 
       
    36 
       
    37 TMediaWriteMan::TMediaWriteMan()
       
    38 :   iActive(EFalse),
       
    39     iOffset(0),
       
    40 	iMediaWriteSize(KDefaultMediaWriteSize)
       
    41     {
       
    42     }
       
    43 
       
    44 void TMediaWriteMan::ReportHighSpeedDevice()
       
    45 	{
       
    46     __MSFNLOG
       
    47 	iMediaWriteSize = KHsMediaWriteSize;
       
    48 	__PRINT1(_L("HS Device reported: SCSI will use %d bytes disk write size"), iMediaWriteSize);
       
    49 	}
       
    50 
       
    51 
       
    52 TInt64 TMediaWriteMan::Start(TUint32 aLba, TUint32 aLength, TUint32 aBlockSize)
       
    53     {
       
    54     iActive = ETrue;
       
    55     iOffset = static_cast<TInt64>(aLba) * aBlockSize;
       
    56     iBytesRemain = aLength * aBlockSize;
       
    57 
       
    58 	TInt64 theEnd = iOffset + iBytesRemain;
       
    59     return theEnd;
       
    60     }
       
    61 
       
    62 TUint32 TMediaWriteMan::NextPacket()
       
    63     {
       
    64     iActive = ETrue;
       
    65     return (iBytesRemain < iMediaWriteSize) ? iBytesRemain : iMediaWriteSize;
       
    66     }
       
    67 
       
    68 
       
    69 void TMediaWriteMan::Reset()
       
    70     {
       
    71     iActive = EFalse;
       
    72     iOffset = 0;
       
    73     }
       
    74 
       
    75 void TMediaWriteMan::SetOffset(const TInt64& aOffset, TUint aLength)
       
    76     {
       
    77     iOffset = aOffset + aLength;
       
    78     iBytesRemain -= aLength;
       
    79     }
       
    80 
       
    81 TUint32 TMediaWriteMan::GetPacketLength() const
       
    82     {
       
    83     // KMaxBufSize or the MediaWriteSize, whichever is smallest.
       
    84 	TUint32 thisLength = (iBytesRemain > KMaxBufSize) ? KMaxBufSize : iBytesRemain;
       
    85 	thisLength = (thisLength > iMediaWriteSize) ? iMediaWriteSize : thisLength;
       
    86     return thisLength;
       
    87     }
       
    88 
       
    89 
       
    90 /**
       
    91 Creates the CScsiProtocol object.  Called during controller initialisation.
       
    92 
       
    93 @param aDriveManager reference to the drive manager object
       
    94 */
       
    95 CScsiServerProtocol* CScsiServerProtocol::NewL(CDriveManager& aDriveManager)
       
    96 	{
       
    97     __MSFNSLOG
       
    98 	CScsiServerProtocol* self = new (ELeave) CScsiServerProtocol(aDriveManager);
       
    99 	CleanupStack::PushL(self);
       
   100 	self->ConstructL();
       
   101 	CleanupStack::Pop();
       
   102 	return self;
       
   103 	}
       
   104 
       
   105 #ifdef MSDC_TESTMODE
       
   106 CScsiServerProtocol* CScsiServerProtocol::NewL(CDriveManager& aDriveManager, TTestParser* aTestParser)
       
   107 	{
       
   108     __MSFNSLOG
       
   109 	CScsiServerProtocol* self = new (ELeave) CScsiServerProtocol(aDriveManager, aTestParser);
       
   110 	CleanupStack::PushL(self);
       
   111 	self->ConstructL();
       
   112 	CleanupStack::Pop();
       
   113 	return self;
       
   114 	}
       
   115 #endif
       
   116 
       
   117 
       
   118 /**
       
   119 c'tor
       
   120 
       
   121 @param aDriveManager reference to the drive manager object
       
   122 */
       
   123 CScsiServerProtocol::CScsiServerProtocol(CDriveManager& aDriveManager)
       
   124 :   iDriveManager(aDriveManager)
       
   125 	{
       
   126     __MSFNLOG
       
   127 
       
   128 	iWriteTransferPublisher = CUsbWriteTransferPublisher::NewL(iBytesWritten);
       
   129 	iReadTransferPublisher = CUsbReadTransferPublisher::NewL(iBytesRead);
       
   130 
       
   131 	for (TUint i = 0; i < KUsbMsMaxDrives; i++)
       
   132 		{
       
   133 		iBytesRead[i] = 0;
       
   134 		iBytesWritten[i] = 0;
       
   135 		}
       
   136 	}
       
   137 
       
   138 #ifdef MSDC_TESTMODE
       
   139 CScsiServerProtocol::CScsiServerProtocol(CDriveManager& aDriveManager, TTestParser* aTestParser)
       
   140 :   iDriveManager(aDriveManager),
       
   141     iTestParser(aTestParser)
       
   142 	{
       
   143     __MSFNLOG
       
   144 
       
   145 	iWriteTransferPublisher = CUsbWriteTransferPublisher::NewL(iBytesWritten);
       
   146 	iReadTransferPublisher = CUsbReadTransferPublisher::NewL(iBytesRead);
       
   147 
       
   148 	for (TUint i = 0; i < KUsbMsMaxDrives; i++)
       
   149 		{
       
   150 		iBytesRead[i] = 0;
       
   151 		iBytesWritten[i] = 0;
       
   152 		}
       
   153 	}
       
   154 #endif
       
   155 
       
   156 
       
   157 CScsiServerProtocol::~CScsiServerProtocol()
       
   158 	{
       
   159     __MSFNLOG
       
   160     iDataBuf.Close();
       
   161 	delete iWriteTransferPublisher;
       
   162 	delete iReadTransferPublisher;
       
   163 	}
       
   164 
       
   165 
       
   166 void CScsiServerProtocol::ConstructL()
       
   167 	{
       
   168     __MSFNLOG
       
   169 	}
       
   170 
       
   171 
       
   172 /**
       
   173 Associates the transport with the protocol. Called during initialisation of the controller.
       
   174 
       
   175 @param aTransport pointer to the transport object
       
   176 */
       
   177 void CScsiServerProtocol::RegisterTransport(MDeviceTransport* aTransport)
       
   178 	{
       
   179     __MSFNLOG
       
   180 	iTransport = aTransport;
       
   181 	}
       
   182 
       
   183 
       
   184 /**
       
   185 Called by the Transport when it detects that the USB device is either running
       
   186 at High Speed or is at least capable of HS operation. The Protocol can use this
       
   187 information (for instance) to select the optimal write block size to use.
       
   188 
       
   189 This function is preferably called before actual MS data transfer operation
       
   190 starts, and usually only once.
       
   191 
       
   192 */
       
   193 void CScsiServerProtocol::ReportHighSpeedDevice()
       
   194 	{
       
   195     __MSFNLOG
       
   196     iMediaWriteMan.ReportHighSpeedDevice();
       
   197 	}
       
   198 
       
   199 
       
   200 void CScsiServerProtocol::SetParameters(const TMassStorageConfig& aConfig)
       
   201 	{
       
   202     __MSFNLOG
       
   203 	iConfig = aConfig;
       
   204 	}
       
   205 
       
   206 
       
   207 /**
       
   208 Called by the transport layer when a packet is available for decoding.
       
   209 If an error occurs, the sense code is updated and EFalse is returned.
       
   210 
       
   211 @param aData
       
   212 
       
   213 @return  ETrue if command was decoded and executed successfully
       
   214 */
       
   215 TBool CScsiServerProtocol::DecodePacket(TPtrC8& aData, TUint8 aLun)
       
   216 	{
       
   217     __MSFNLOG
       
   218     TScsiServerReq* cdb = NULL;
       
   219     TRAPD(err, cdb = cdb->CreateL(static_cast<TScsiServerReq::TOperationCode>(aData[0]), aData));
       
   220 
       
   221     TBool decodeGood = EFalse;
       
   222     if (err == KErrNotSupported)
       
   223     	iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidCmdCode);
       
   224 	else if (err != KErrNone)
       
   225 		iSenseInfo.SetSense(TSenseInfo::EAbortedCommand, TSenseInfo::EInsufficientRes);
       
   226     else if (cdb->iNaca) // Check the CONTROL byte
       
   227 		iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb);
       
   228     else if (cdb->iLink)
       
   229         iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb);
       
   230     else
       
   231         {
       
   232         TScsiServerReq::TOperationCode operationCode = cdb->iOperationCode;
       
   233         if (aLun > iDriveManager.MaxLun())
       
   234             {
       
   235             __PRINT(_L("No drive available\n"));
       
   236             iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::ELuNotSupported);
       
   237             }
       
   238         else
       
   239             {
       
   240             iLun = aLun;
       
   241             if (operationCode != TScsiServerReq::ERequestSense)
       
   242                 {
       
   243                 iSenseInfo.SetSense(TSenseInfo::ENoSense);
       
   244                 }
       
   245 
       
   246             switch (operationCode)
       
   247                 {
       
   248             case TScsiServerReq::ETestUnitReady:
       
   249                 HandleUnitReady();
       
   250                 break;
       
   251 
       
   252             case TScsiServerReq::ERequestSense:
       
   253                 HandleRequestSense(*cdb);
       
   254                 break;
       
   255 
       
   256             case TScsiServerReq::EInquiry:
       
   257                 HandleInquiry(*cdb);
       
   258                 break;
       
   259 
       
   260             case TScsiServerReq::EModeSense6:
       
   261                 HandleModeSense6(*cdb);
       
   262                 break;
       
   263 
       
   264             case TScsiServerReq::EStartStopUnit:
       
   265                 HandleStartStopUnit(*cdb);
       
   266                 break;
       
   267 
       
   268             case TScsiServerReq::EPreventMediaRemoval:
       
   269                 HandlePreventMediaRemoval(*cdb);
       
   270                 break;
       
   271 
       
   272             case TScsiServerReq::EReadCapacity10:
       
   273                 HandleReadCapacity10(*cdb);
       
   274                 break;
       
   275 
       
   276             case TScsiServerReq::ERead10:
       
   277                 HandleRead10(*cdb);
       
   278                 break;
       
   279 
       
   280             case TScsiServerReq::EWrite10:
       
   281                 HandleWrite10(*cdb);
       
   282                 break;
       
   283 
       
   284             case TScsiServerReq::EReadFormatCapacities:
       
   285                 HandleReadFormatCapacities(*cdb);
       
   286                 break;
       
   287 
       
   288             default:
       
   289                 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidCmdCode);
       
   290                 break;
       
   291                 }
       
   292             }
       
   293         __PRINT1(_L("DecodePacket result = %d"), iSenseInfo.SenseOk());
       
   294     	decodeGood = iSenseInfo.SenseOk();
       
   295         }
       
   296 
       
   297     delete cdb;
       
   298     return decodeGood;
       
   299 	}
       
   300 
       
   301 
       
   302 /**
       
   303 Checks if drive ready
       
   304 
       
   305 @param aLun Logic unit number
       
   306 @return pointer to drive correspondent to LUN if drive mounted and ready, NULL otherwise
       
   307 */
       
   308 CMassStorageDrive* CScsiServerProtocol::GetCheckDrive()
       
   309 	{
       
   310     __MSFNLOG
       
   311 #ifdef MSDC_TESTMODE
       
   312     if (iTestParser && iTestParser->SenseError() != TTestParser::ETestSenseErrorNoSense)
       
   313         {
       
   314         switch (iTestParser->SenseError())
       
   315             {
       
   316             case TTestParser::ETestSenseErrorMediaNotPresent:
       
   317                 __TESTMODEPRINT("Set SENSE ERROR(ENotReady, EMediaNotPresent)");
       
   318                 iSenseInfo.SetSense(TSenseInfo::ENotReady,
       
   319                                     TSenseInfo::EMediaNotPresent);
       
   320                 break;
       
   321 
       
   322 
       
   323             case TTestParser::ETestSenseErrorUnitAttention:
       
   324             default:
       
   325                 __TESTMODEPRINT("Set SENSE ERROR(EUnitAttention, ENotReadyToReadyChange)");
       
   326                 iSenseInfo.SetSense(TSenseInfo::EUnitAttention,
       
   327                                     TSenseInfo::ENotReadyToReadyChange);
       
   328                 break;
       
   329             }
       
   330         iTestParser->ClrSenseError();
       
   331         return NULL;
       
   332         }
       
   333 #endif
       
   334 
       
   335 	CMassStorageDrive* drive = iDriveManager.Drive(iLun);
       
   336 	CMassStorageDrive::TMountState mountState = drive->MountState();
       
   337 
       
   338 	if (mountState == CMassStorageDrive::EDisconnected || mountState == CMassStorageDrive::EConnecting)
       
   339 		{
       
   340 		__PRINT(_L("Drive disconnected\n"));
       
   341 		iSenseInfo.SetSense(TSenseInfo::ENotReady,
       
   342 							TSenseInfo::EMediaNotPresent);
       
   343 		return NULL;
       
   344 		}
       
   345 
       
   346 	TLocalDriveRef::TDriveState state = drive->CheckDriveState();
       
   347 	if (state == TLocalDriveRef::EMediaNotPresent || state == TLocalDriveRef::ELocked)
       
   348 		{
       
   349 		__PRINT1(_L("Media not present or locked. (state =0x%X)\n"),state);
       
   350 		iSenseInfo.SetSense(TSenseInfo::ENotReady, TSenseInfo::EMediaNotPresent);
       
   351 		return NULL;
       
   352 		}
       
   353 
       
   354 	if (drive->IsMediaChanged(ETrue))  //reset "media changed" status
       
   355 		{
       
   356 		__PRINT(_L("Media was changed\n"));
       
   357 		// SAM-2 Section 5.9.5 Unit Attention Condition
       
   358 		iSenseInfo.SetSense(TSenseInfo::EUnitAttention, TSenseInfo::ENotReadyToReadyChange);
       
   359 		iDriveManager.Connect(iLun);   //publish event to USB app
       
   360 		return NULL;
       
   361 		}
       
   362 
       
   363 	if (mountState == CMassStorageDrive::EDisconnecting)
       
   364 		{
       
   365 		__PRINT(_L("Drive disconnecting\n"));
       
   366 		iSenseInfo.SetSense(TSenseInfo::ENotReady,
       
   367 							TSenseInfo::EMediaNotPresent);
       
   368 		return NULL;
       
   369 		}
       
   370 
       
   371 	return drive;
       
   372 	}
       
   373 
       
   374 
       
   375 /**
       
   376 Command Parser for the UNIT READY command (0x00)
       
   377 
       
   378 @param aLun Logic unit number
       
   379 @return ETrue if successful,
       
   380 */
       
   381 TBool CScsiServerProtocol::HandleUnitReady()
       
   382 	{
       
   383     __MSFNLOG
       
   384 	return GetCheckDrive() ? ETrue : EFalse;
       
   385 	}
       
   386 
       
   387 
       
   388 /**
       
   389 Command Parser for the REQUEST SENSE command (0x03)
       
   390 
       
   391 @return ETrue if successful,
       
   392 */
       
   393 TBool CScsiServerProtocol::HandleRequestSense(const TScsiServerReq& aRequest)
       
   394 	{
       
   395     __MSFNLOG
       
   396     const TScsiServerRequestSenseReq request = static_cast<const TScsiServerRequestSenseReq&>(aRequest);
       
   397 	__PRINT1(_L("length = %d\n"), request.iAllocationLength);
       
   398 
       
   399     TScsiServerRequestSenseResp requestSense;
       
   400     requestSense.iAllocationLength = request.iAllocationLength;
       
   401 
       
   402     requestSense.SetResponseCode(TScsiServerRequestSenseResp::ECurrentErrors);
       
   403     requestSense.iSensePtr = &iSenseInfo;
       
   404     requestSense.Encode(iCommandBuf);
       
   405 
       
   406 	__PRINT4(_L("Response=0x%x Sense=0x%x, Additional=0x%x, Qualifier=0x%x\n"),
       
   407 				iCommandBuf[0], iCommandBuf[02], iCommandBuf[12], iCommandBuf[13]);
       
   408 
       
   409 	TPtrC8 writeBuf = iCommandBuf.Left(request.iAllocationLength);
       
   410 	iTransport->SetupDataIn(writeBuf);
       
   411 
       
   412 	// clear the sense info
       
   413 	iSenseInfo.SetSense(TSenseInfo::ENoSense);
       
   414 	return ETrue;
       
   415 	}
       
   416 
       
   417 
       
   418 /**
       
   419 Command Parser for the INQUIRY command (0x12)
       
   420 
       
   421 @param aLun Logic unit number
       
   422 @return ETrue if successful,
       
   423 */
       
   424 TBool CScsiServerProtocol::HandleInquiry(const TScsiServerReq& aRequest)
       
   425 	{
       
   426     __MSFNLOG
       
   427     const TScsiServerInquiryReq request = static_cast<const TScsiServerInquiryReq&>(aRequest);
       
   428 
       
   429 	if (request.iCmdDt || request.iEvpd || request.iPage || iLun >= KUsbMsMaxDrives)
       
   430 		{
       
   431 		iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb);
       
   432 		return EFalse;
       
   433 		}
       
   434 
       
   435     TScsiServerInquiryResp inquiry(iConfig);
       
   436 
       
   437     inquiry.SetAllocationLength(request.iAllocationLength);
       
   438 
       
   439 #ifdef MSDC_TESTMODE
       
   440     if (iTestParser && !iTestParser->Removable())
       
   441         {
       
   442         __TESTMODEPRINT("RMB Cleared");
       
   443         inquiry.SetNotRemovable();
       
   444         }
       
   445 #endif
       
   446 
       
   447     inquiry.Encode(iCommandBuf);
       
   448 
       
   449     TUint length = inquiry.Length();
       
   450 
       
   451 	TPtrC8 writeBuf = iCommandBuf.Left(length);
       
   452 	iTransport->SetupDataIn(writeBuf);
       
   453 
       
   454 	iSenseInfo.SetSense(TSenseInfo::ENoSense);
       
   455 	return ETrue;
       
   456 	}
       
   457 
       
   458 
       
   459 /**
       
   460  Command Parser for the START STOP UNIT command (0x1B)
       
   461 
       
   462  @param aData command data (started form position 1)
       
   463  @param aLun Logic unit number
       
   464  @return ETrue if successful, TFalse otherwise
       
   465  */
       
   466 TBool CScsiServerProtocol::HandleStartStopUnit(const TScsiServerReq& aRequest)
       
   467 	{
       
   468     __MSFNLOG
       
   469 
       
   470 	const TScsiServerStartStopUnitReq request = static_cast<const TScsiServerStartStopUnitReq&>(aRequest);
       
   471 
       
   472 	if (request.iLoej)
       
   473 		{
       
   474 		if(request.iStart)	//Start unit
       
   475 			{
       
   476 			iDriveManager.Connect(iLun);
       
   477 			__PRINT(_L("Load media\n"));
       
   478 
       
   479             // rd/wr publisher
       
   480 			iBytesRead[iLun] = 0;
       
   481 			iBytesWritten[iLun] = 0;
       
   482 
       
   483 			// publish the initial values
       
   484 			iWriteTransferPublisher->DoPublishDataTransferredEvent();
       
   485 			iReadTransferPublisher->DoPublishDataTransferredEvent();
       
   486 			}
       
   487 		else		//Stop unit
       
   488 			{
       
   489 			iDriveManager.SetCritical(iLun, EFalse);
       
   490 			iDriveManager.Disconnect(iLun);
       
   491 			__PRINT(_L("Unload media\n"));
       
   492 			}
       
   493 		}
       
   494 
       
   495 	if (request.iImmed)
       
   496 		{
       
   497 		return ETrue;
       
   498 		}
       
   499 
       
   500 	CMassStorageDrive* drive = iDriveManager.Drive(iLun);
       
   501 
       
   502 	TInt  timeLeft (20);   // 1 sec timeout
       
   503 	CMassStorageDrive::TMountState mountState;
       
   504 
       
   505 	do
       
   506 		{
       
   507 		User::After(1000 * 50);		// 50 mSec
       
   508 		--timeLeft;
       
   509 		mountState = drive->MountState();
       
   510 
       
   511 		if ((!request.iStart && mountState != CMassStorageDrive::EConnected)
       
   512 			 ||
       
   513 			 (request.iStart &&
       
   514 				(mountState == CMassStorageDrive::EDisconnecting ||
       
   515                mountState == CMassStorageDrive::EConnected)))
       
   516 			{
       
   517 			return ETrue;
       
   518 			}
       
   519 		} while (timeLeft>0);
       
   520 
       
   521 	//timeout happend
       
   522 	iSenseInfo.SetSense(TSenseInfo::ENotReady,
       
   523 						TSenseInfo::EAscLogicalUnitDoesNotRespondToSelection);
       
   524 	return EFalse;
       
   525 	}
       
   526 
       
   527 
       
   528 /**
       
   529 Command Parser for the PREVENT/ALLOW MEDIA REMOVAL command (0x1E)
       
   530 
       
   531 @param aData command data (started form position 1)
       
   532 @param aLun Logic unit number
       
   533 @return ETrue if successful.
       
   534 */
       
   535 TBool CScsiServerProtocol::HandlePreventMediaRemoval(const TScsiServerReq& aRequest)
       
   536 	{
       
   537     __MSFNLOG
       
   538 	const TScsiServerPreventMediaRemovalReq& request = static_cast<const TScsiServerPreventMediaRemovalReq&>(aRequest);
       
   539 	__FNLOG("CScsiProtocol::HandlePreventMediaRemoval");
       
   540 	CMassStorageDrive* drive = GetCheckDrive();
       
   541 
       
   542 	if (drive == NULL)
       
   543 		{
       
   544 		return EFalse;
       
   545 		}
       
   546 	iDriveManager.SetCritical(iLun, request.iPrevent);
       
   547 	return ETrue;
       
   548 	}
       
   549 
       
   550 
       
   551 /** Cancel active state, Invoked by transnport when it stops */
       
   552 TInt CScsiServerProtocol::Cancel()
       
   553 	{
       
   554     __MSFNLOG
       
   555 	iDriveManager.SetCritical(CDriveManager::KAllLuns, EFalse);
       
   556 	return KErrNone;
       
   557 	}
       
   558 
       
   559 
       
   560 TBool CScsiServerProtocol::HandleReadFormatCapacities(const TScsiServerReq& aRequest)
       
   561 /**
       
   562  * Command Parser for the READ FORMAT CAPACITIES command (0x23)
       
   563  *
       
   564  * @return ETrue if successful, else a standard Symbian OS error code.
       
   565  */
       
   566 	{
       
   567     __MSFNLOG
       
   568 	const TScsiServerReadFormatCapacitiesReq& request = static_cast<const TScsiServerReadFormatCapacitiesReq&>(aRequest);
       
   569 
       
   570     CMassStorageDrive* drive = NULL;
       
   571     for (TInt i = 0; i < 10; i++)
       
   572         {
       
   573         drive = GetCheckDrive();
       
   574         if (drive)
       
   575             {
       
   576             break;
       
   577             }
       
   578         User::After(100000);
       
   579         }
       
   580 
       
   581 	if (!drive)
       
   582 		{
       
   583         return EFalse;
       
   584 		}
       
   585 
       
   586 	TUint32 numBlocks = I64LOW(drive->MediaParams().NumBlocks());
       
   587 
       
   588     TScsiServerReadFormatCapacitiesResp response(request.AllocationLength());
       
   589     response.SetNumberBlocks(numBlocks);
       
   590 
       
   591     response.Encode(iCommandBuf);
       
   592 	TPtrC8 writeBuf = iCommandBuf;
       
   593 	iTransport->SetupDataIn(writeBuf);
       
   594 	return ETrue;
       
   595 	}
       
   596 
       
   597 
       
   598 /**
       
   599 Command Parser for the READ CAPACITY(10) command (0x25)
       
   600 
       
   601 @param aData command data (started form position 1)
       
   602 @param aLun Logic unit number
       
   603 @return ETrue if successful.
       
   604 */
       
   605 TBool CScsiServerProtocol::HandleReadCapacity10(const TScsiServerReq& aRequest)
       
   606 	{
       
   607     __MSFNLOG
       
   608 	const TScsiServerReadCapacity10Req& request = static_cast<const TScsiServerReadCapacity10Req&>(aRequest);
       
   609 	CMassStorageDrive* drive = GetCheckDrive();
       
   610 	if (drive == NULL)
       
   611 		{
       
   612 		return EFalse;
       
   613 		}
       
   614 
       
   615 	if (request.iPmi || request.iLogicalBlockAddress)   //do not support partial medium indicator
       
   616 		{
       
   617 		iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb);
       
   618 		return EFalse;
       
   619 		}
       
   620 
       
   621     TScsiServerReadCapacity10Resp response;
       
   622     response.Set(drive->MediaParams().BlockSize(), drive->MediaParams().NumBlocks());
       
   623     response.Encode(iCommandBuf);
       
   624 
       
   625 	TPtrC8 writeBuf = iCommandBuf;
       
   626 	iTransport->SetupDataIn(writeBuf);
       
   627 
       
   628 	return KErrNone;
       
   629 	}
       
   630 
       
   631 
       
   632 /**
       
   633 Command Parser for the READ10 command (0x28)
       
   634 
       
   635 @param aData command data (started form position 1)
       
   636 @param aLun Logic unit number
       
   637 @return ETrue if successful.
       
   638 */
       
   639 TBool CScsiServerProtocol::HandleRead10(const TScsiServerReq& aRequest)
       
   640 	{
       
   641     __MSFNLOG
       
   642 	const TScsiServerRead10Req& request = static_cast<const TScsiServerRead10Req&>(aRequest);
       
   643 	CMassStorageDrive* drive = GetCheckDrive();
       
   644 	if (drive == NULL)
       
   645 		{
       
   646 		return EFalse;
       
   647 		}
       
   648 
       
   649 	if (request.iProtect)
       
   650 		{
       
   651 		iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb);
       
   652 		return EFalse;
       
   653 		}
       
   654 
       
   655 	if (!request.iTransferLength)
       
   656 		{
       
   657 		return ETrue; // do nothing - this is not an error
       
   658 		}
       
   659 
       
   660     TUint32 blockSize = drive->MediaParams().BlockSize();
       
   661 
       
   662 	const TInt64 bOffset = static_cast<TInt64>(request.iLogicalBlockAddress) * blockSize;
       
   663 	const TInt bLength = request.iTransferLength * blockSize;
       
   664 	const TInt64 theEnd = bOffset + bLength;
       
   665 
       
   666 	if (theEnd > drive->MediaParams().Size())  //check if media big enough for this request
       
   667 		{
       
   668 		__PRINT(_L("err - Request ends out of media\n"));
       
   669 		iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::ELbaOutOfRange);
       
   670 		return EFalse;
       
   671 		}
       
   672 
       
   673 	// check if our buffer can hold requested data
       
   674 	if (iDataBuf.MaxLength() < bLength)
       
   675 		{
       
   676         TRAPD(err,iDataBuf.ReAllocL(bLength));
       
   677         if (err)
       
   678             {
       
   679             __PRINT(_L("err - Buffer too small\n"));
       
   680             iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb);
       
   681             return EFalse;
       
   682             }
       
   683 		}
       
   684 
       
   685     iDataBuf.SetLength(bLength);
       
   686 	TInt err = drive->Read(bOffset, bLength, iDataBuf);
       
   687 	if (err != KErrNone)
       
   688 		{
       
   689 		__PRINT1(_L("Read failed, err=%d\n"), err);
       
   690 		iSenseInfo.SetSense(TSenseInfo::ENotReady, TSenseInfo::EMediaNotPresent);
       
   691 		return EFalse;
       
   692 		}
       
   693 
       
   694 	TPtrC8 writeBuf = iDataBuf;
       
   695 
       
   696     // rd publisher
       
   697 	iBytesRead[iLun] += writeBuf.Length();
       
   698 	iReadTransferPublisher->StartTimer();
       
   699 
       
   700 	// Set up data write to the host
       
   701 #ifdef MSDC_TESTMODE
       
   702     if (iTestParser)
       
   703         {
       
   704         TBool test = iTestParser->DInSearch(writeBuf);
       
   705         }
       
   706 #endif
       
   707 	iTransport->SetupDataIn(writeBuf);
       
   708 	return ETrue;
       
   709 	}
       
   710 
       
   711 
       
   712 /**
       
   713 Command Parser for the WRITE(10) command (0x2A)
       
   714 
       
   715 @param aData command data (started form position 1)
       
   716 @param aLun Logic unit number
       
   717 @return ETrue if successful.
       
   718 */
       
   719 TBool CScsiServerProtocol::HandleWrite10(const TScsiServerReq& aRequest)
       
   720 	{
       
   721     __MSFNLOG
       
   722 	const TScsiServerWrite10Req& request = static_cast<const TScsiServerWrite10Req&>(aRequest);
       
   723 	CMassStorageDrive* drive = GetCheckDrive();
       
   724 	if (drive == NULL)
       
   725 		{
       
   726 		return EFalse;
       
   727 		}
       
   728 	if (request.iProtect)
       
   729 		{
       
   730 		iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb);
       
   731 		return EFalse;
       
   732 		}
       
   733 
       
   734 	if (!request.iTransferLength)
       
   735 		{
       
   736 		return ETrue; // do nothing - this is not an error
       
   737 		}
       
   738 
       
   739     const TMediaParams& params = drive->MediaParams();
       
   740 
       
   741 	if (params.IsWriteProtected() ||
       
   742 		params.IsLocked())
       
   743 		{
       
   744 		iSenseInfo.SetSense(TSenseInfo::EDataProtection, TSenseInfo::EWriteProtected);
       
   745 		return EFalse;
       
   746 		}
       
   747 
       
   748     TInt64 theEnd = iMediaWriteMan.Start(request.iLogicalBlockAddress, request.iTransferLength, params.BlockSize());
       
   749 	if (theEnd > params.Size())  //check if media big enough for this request
       
   750 		{
       
   751 		__PRINT(_L("err - Request ends out of media\n"));
       
   752 		iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::ELbaOutOfRange);
       
   753 		return EFalse;
       
   754 		}
       
   755 
       
   756     TUint32 thisLength = iMediaWriteMan.GetPacketLength();
       
   757 
       
   758     // check if our buffer can hold requested data
       
   759     if (iDataBuf.MaxLength() < thisLength)
       
   760         {
       
   761         TRAPD(err,iDataBuf.ReAllocL(thisLength));
       
   762         if (err)
       
   763             {
       
   764             __PRINT(_L("err - Buffer too small\n"));
       
   765             iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb);
       
   766             return EFalse;
       
   767             }
       
   768         }
       
   769 
       
   770 	iDataBuf.SetLength(thisLength);
       
   771 	TPtr8 readBuf = iDataBuf.LeftTPtr(iDataBuf.Length());
       
   772 
       
   773     // wr publisher
       
   774 	iBytesWritten[iLun] += readBuf.Length();
       
   775 	iWriteTransferPublisher->StartTimer();
       
   776 	iTransport->SetupDataOut(readBuf);
       
   777 	return ETrue;
       
   778 	}
       
   779 
       
   780 
       
   781 void CScsiServerProtocol::MediaWriteAbort()
       
   782     {
       
   783     __MSFNLOG
       
   784     iMediaWriteMan.Reset();
       
   785     iSenseInfo.SetSense(TSenseInfo::EAbortedCommand);
       
   786     }
       
   787 
       
   788 /**
       
   789 Called by the transport when the requested data has been read or an error has
       
   790 occurred during the read.
       
   791 
       
   792 @param aError Indicate if an error occurs during reading data by transport.
       
   793 @return KErrAbort if command processing is complete but has failed,
       
   794         KErrCompletion if sufficient data is available in the buffer to process
       
   795         the transfer immediately, KErrNotReady if insufficient data is
       
   796         available in the buffer so the transport should wait for it to arrive,
       
   797         KErrNone if command processing is complete and was successful.
       
   798 */
       
   799 TInt CScsiServerProtocol::MediaWritePacket(TUint& aBytesWritten)
       
   800 	{
       
   801     __MSFNLOG
       
   802     aBytesWritten = 0;
       
   803     if (iMediaWriteMan.Active() == EFalse)
       
   804         {
       
   805         iSenseInfo.SetSense(TSenseInfo::EAbortedCommand);
       
   806         return KErrAbort;
       
   807         }
       
   808 
       
   809     CMassStorageDrive* drive = GetCheckDrive();
       
   810     if (drive == NULL)
       
   811         {
       
   812         return KErrAbort;
       
   813         }
       
   814 
       
   815 #ifdef MSDC_TESTMODE
       
   816     if (iTestParser && iTestParser->Enabled())
       
   817         {
       
   818         TInt testCase = iTestParser->TestCase();
       
   819         if (testCase == TTestParser::ETestCaseDoStallData)
       
   820             {
       
   821             iTestParser->DecTestCounter();
       
   822 
       
   823             TInt testCounter = iTestParser->TestCounter();
       
   824             if (testCounter == 1)
       
   825                 {
       
   826                 __TESTMODEPRINT1("Aborting MediaWritePacket (Data Stall) x%x", iMediaWriteMan.BytesRemain());
       
   827                 __TESTMODEPRINT2("Offset=0x%lx Length=%x",
       
   828                                  iMediaWriteMan.Offset(), iDataBuf.Length());
       
   829                 return KErrNone;
       
   830                 }
       
   831             else if (testCounter == 0)
       
   832                 {
       
   833                 // Display the next write and clear the test
       
   834                 iTestParser->ClrTestCase();
       
   835                 __TESTMODEPRINT2("Offset=0x%lx Length=%x",
       
   836                                  iMediaWriteMan.Offset(), iDataBuf.Length());
       
   837                 }
       
   838             }
       
   839         else if (testCase == TTestParser::ETestCaseDoResidue)
       
   840             {
       
   841             iTestParser->DecTestCounter();
       
   842             TInt testCounter = iTestParser->TestCounter();
       
   843 
       
   844             if (testCounter == 1)
       
   845                 {
       
   846                 // abort write and leave residue
       
   847                 __TESTMODEPRINT1("Aborting MediaWritePacket (Data Residue) x%x", iMediaWriteMan.BytesRemain());
       
   848                 __TESTMODEPRINT2("Offset=0x%lx Length=0x%x",
       
   849                                  iMediaWriteMan.Offset(), iDataBuf.Length());
       
   850                 aBytesWritten = 0;
       
   851                 return KErrAbort;
       
   852                 }
       
   853             else if (testCounter == 0)
       
   854                 {
       
   855                 // Display the next write and clear the test
       
   856                 iTestParser->ClrTestCase();
       
   857                 __TESTMODEPRINT2("MediaWritePacket Offset=0x%lx Length=0x%x",
       
   858                                  iMediaWriteMan.Offset(), iDataBuf.Length());
       
   859                 }
       
   860             else
       
   861                 {
       
   862                 __TESTMODEPRINT3("MediaWritePacket[%x] Offset=0x%lx Length=0x%x",
       
   863                                  testCounter, iMediaWriteMan.Offset(), iDataBuf.Length());
       
   864                 }
       
   865 
       
   866             }
       
   867         }
       
   868 #endif
       
   869 
       
   870 	const TInt64 bOffset = iMediaWriteMan.Offset();
       
   871     iMediaWriteMan.Reset();
       
   872 
       
   873    	__PRINT1(_L("SCSI: writing %d bytes\n"), iDataBuf.Length());
       
   874 
       
   875     TInt err = KErrNone;
       
   876 #ifdef MSDC_TESTMODE
       
   877     if (iTestParser)
       
   878         {
       
   879         TBool test = iTestParser->DoutSearch(iDataBuf);
       
   880         if (test)
       
   881             {
       
   882             // Do not write test control blocks to media
       
   883             }
       
   884         else
       
   885             {
       
   886             // ********* Write data to the drive ********
       
   887             err = drive->Write(bOffset, iDataBuf);
       
   888             }
       
   889         }
       
   890 #else
       
   891     // ********* Write data to the drive ********
       
   892    	err = drive->Write(bOffset, iDataBuf);
       
   893 #endif
       
   894    	if (err != KErrNone)
       
   895    		{
       
   896    		__PRINT1(_L("Error after write = 0x%X \n"), err);
       
   897    		iSenseInfo.SetSense(TSenseInfo::EAbortedCommand);
       
   898    		return KErrAbort;
       
   899    		}
       
   900 
       
   901    	TUint thisLength = iDataBuf.Length();
       
   902     aBytesWritten = thisLength;
       
   903 
       
   904     iMediaWriteMan.SetOffset(bOffset, thisLength);
       
   905 
       
   906    	if (iMediaWriteMan.BytesRemain() == 0)
       
   907         {
       
   908         return iSenseInfo.SenseOk() ? KErrNone : KErrAbort;
       
   909         }
       
   910 
       
   911     // More data is expected - set up another request to read from the host
       
   912     const TUint32 nextPacketLength = iMediaWriteMan.NextPacket();
       
   913  	TUint bytesAvail = iTransport->BytesAvailable() & ~(drive->MediaParams().BlockSize()-1);
       
   914 
       
   915  	TBool wait = EFalse;
       
   916 
       
   917     thisLength = nextPacketLength;
       
   918     if (bytesAvail)
       
   919         {
       
   920         if (bytesAvail < nextPacketLength)
       
   921             {
       
   922             // Not enough data is available at the transport to satisfy the
       
   923             // request, so return KErrNotReady to indicate that the transport
       
   924             // should wait.
       
   925             thisLength = nextPacketLength;
       
   926             wait = ETrue;
       
   927             }
       
   928         }
       
   929 
       
   930  	thisLength = (thisLength > KMaxBufSize) ? KMaxBufSize : thisLength;
       
   931 
       
   932    	iDataBuf.SetLength(thisLength);
       
   933    	TPtr8 readBuf = iDataBuf.LeftTPtr(iDataBuf.Length());
       
   934     iTransport->SetupDataOut(readBuf);
       
   935     return wait ? KErrNotReady : KErrCompletion;
       
   936 	}
       
   937 
       
   938 
       
   939 /**
       
   940 Command Parser for the MODE SENSE(06) command (0x1A)
       
   941 
       
   942 @return ETrue if successful.
       
   943 */
       
   944 TBool CScsiServerProtocol::HandleModeSense6(const TScsiServerReq& aRequest)
       
   945 	{
       
   946     __MSFNLOG
       
   947 	const TScsiServerModeSense6Req& request = static_cast<const TScsiServerModeSense6Req&>(aRequest);
       
   948 
       
   949 	TScsiServerModeSense6Resp response;
       
   950     response.SetAllocationLength(request.iAllocationLength);
       
   951 
       
   952 	if (request.iPageCode != TScsiServerModeSense6Req::KAllPages ||
       
   953         request.iPageControl == TScsiServerModeSense6Req::EChangeableValues)
       
   954 		{
       
   955 		__PRINT(_L("TSenseInfo::EIllegalRequest,TSenseInfo::EInvalidFieldInCdb"));
       
   956 		iSenseInfo.SetSense(TSenseInfo::EIllegalRequest,TSenseInfo::EInvalidFieldInCdb);
       
   957 		return EFalse;
       
   958 		}
       
   959 	if (request.iPageControl != TScsiServerModeSense6Req::EDefaultValues)
       
   960 		{
       
   961 		//check if drive write protected
       
   962 		CMassStorageDrive* drive = GetCheckDrive();
       
   963 		if (drive == NULL)
       
   964 			{
       
   965 			__PRINT(_L("drive == null"));
       
   966 			return EFalse;
       
   967 			}
       
   968 
       
   969 #ifdef MSDC_TESTMODE
       
   970     if (iTestParser)
       
   971         {
       
   972         response.SetWp(iTestParser->WriteProtect());
       
   973         }
       
   974 #else
       
   975         response.SetWp(drive->MediaParams().IsWriteProtected());
       
   976 #endif
       
   977         }
       
   978 
       
   979     response.Encode(iCommandBuf);
       
   980 
       
   981 	TPtrC8 writeBuf = iCommandBuf;
       
   982 	iTransport->SetupDataIn(writeBuf);
       
   983 	return iSenseInfo.SenseOk();
       
   984 	}