userlibandfileserver/fileserver/shostmassstorage/server/protocol/cscsiprotocol.cpp
changeset 102 ef2a444a7410
parent 90 947f0dc9f7a8
child 97 41f0cfe18c80
equal deleted inserted replaced
90:947f0dc9f7a8 102:ef2a444a7410
     1 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
     1 // Copyright (c) 2008-2010 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     3 // This component and the accompanying materials are made available
     4 // under the terms of the License "Eclipse Public License v1.0"
     4 // under the terms of the License "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
    24 #include "msdebug.h"
    24 #include "msdebug.h"
    25 #include "msctypes.h"
    25 #include "msctypes.h"
    26 #include "shared.h"
    26 #include "shared.h"
    27 #include "msgservice.h"
    27 #include "msgservice.h"
    28 
    28 
    29 #include "mscutils.h"
       
    30 
       
    31 #include "mtransport.h"
    29 #include "mtransport.h"
    32 #include "mprotocol.h"
    30 #include "mprotocol.h"
    33 #include "tscsiclientreq.h"
    31 #include "tscsiclientreq.h"
    34 #include "tscsiprimarycmds.h"
    32 #include "tscsiprimarycmds.h"
    35 #include "tscsiblockcmds.h"
    33 #include "tscsiblockcmds.h"
    43 #include "cscsiprotocol.h"
    41 #include "cscsiprotocol.h"
    44 
    42 
    45 #include "usbmshostpanic.h"
    43 #include "usbmshostpanic.h"
    46 
    44 
    47 
    45 
    48 
       
    49 /**
    46 /**
    50 Create the CScsiProtocol object.
    47 Create the CScsiProtocol object.
    51 
    48 
    52 @param aLun The LUN for the device represented by this object
    49 @param aLun The LUN for the device represented by this object
    53 @param aTransport The transport interface
    50 @param aTransport The transport interface
    66     }
    63     }
    67 
    64 
    68 void CScsiProtocol::ConstructL(TLun aLun)
    65 void CScsiProtocol::ConstructL(TLun aLun)
    69     {
    66     {
    70 	__MSFNLOG
    67 	__MSFNLOG
       
    68 	// iState = EEntry;
    71     iFsm = CMassStorageFsm::NewL(*this);
    69     iFsm = CMassStorageFsm::NewL(*this);
    72 	iState = EDisconnected;
       
    73 
    70 
    74     const TInt blockLength = 0x200;
    71     const TInt blockLength = 0x200;
    75 
    72 
    76     iHeadbuf.CreateL(blockLength);
    73     iHeadbuf.CreateL(blockLength);
    77     iTailbuf.CreateL(blockLength);
    74     iTailbuf.CreateL(blockLength);
    97 
    94 
    98 
    95 
    99 void CScsiProtocol::InitialiseUnitL()
    96 void CScsiProtocol::InitialiseUnitL()
   100     {
    97     {
   101 	__MSFNLOG
    98 	__MSFNLOG
       
    99     iState = EDisconnected;
   102 
   100 
   103 	// A device may take time to mount the media. If the device fails attempt to
   101 	// A device may take time to mount the media. If the device fails attempt to
   104 	// retry the connection for a number of seconds
   102 	// retry the connection for a number of seconds
   105     TInt retryCounter = 20;
   103     TInt retryCounter = 20;
   106     do
   104     do
   107         {
   105         {
   108         retryCounter--;
   106         retryCounter--;
   109         iFsm->ConnectLogicalUnitL();
   107         iFsm->ConnectLogicalUnitL();
   110         iState = iFsm->IsConnected() ? EConnected: EDisconnected;
   108         if (iFsm->IsConnected())
   111 
       
   112         if (iState == EConnected)
       
   113             {
   109             {
       
   110             iState = EConnected;
   114             break;
   111             break;
   115             }
   112             }
   116         User::After(1000 * 200);    // 200 mS
   113         User::After(1000 * 200);    // 200 mS
   117         }
   114         }
   118     while (retryCounter);
   115     while (retryCounter);
   160 
   157 
   161 	TInt err = iSbcInterface->Read10L(I64LOW(lba), aCopybuf, len);
   158 	TInt err = iSbcInterface->Read10L(I64LOW(lba), aCopybuf, len);
   162     if (err)
   159     if (err)
   163         {
   160         {
   164         __SCSIPRINT1(_L("READ(10) Err=%d"), err);
   161         __SCSIPRINT1(_L("READ(10) Err=%d"), err);
   165         DoCheckConditionL();
   162         User::LeaveIfError(DoCheckConditionL());
   166         User::LeaveIfError(KErrAbort);
       
   167         }
   163         }
   168 
   164 
   169     // handle residue
   165     // handle residue
   170     while (len != aLen)
   166     while (len != aLen)
   171         {
   167         {
   187 
   183 
   188         // read rest of the block
   184         // read rest of the block
   189         TInt err = iSbcInterface->Read10L(aPos/blockLen, aCopybuf, len);
   185         TInt err = iSbcInterface->Read10L(aPos/blockLen, aCopybuf, len);
   190         if (err)
   186         if (err)
   191             {
   187             {
   192             DoCheckConditionL();
   188             User::LeaveIfError(DoCheckConditionL());
   193             User::LeaveIfError(KErrAbort);
       
   194             }
   189             }
   195         }
   190         }
   196     }
   191     }
   197 
   192 
   198 
   193 
   215     const TInt blockLen = iSbcInterface->iBlockTransfer.BlockLength();
   210     const TInt blockLen = iSbcInterface->iBlockTransfer.BlockLength();
   216     TInt len = aLen;
   211     TInt len = aLen;
   217 	TInt err = iSbcInterface->Write10L(aPos/blockLen, aCopybuf, aOffset, len);
   212 	TInt err = iSbcInterface->Write10L(aPos/blockLen, aCopybuf, aOffset, len);
   218     if (err)
   213     if (err)
   219         {
   214         {
   220         DoCheckConditionL();
   215         User::LeaveIfError(DoCheckConditionL());
   221         User::LeaveIfError(KErrAbort);
       
   222         }
   216         }
   223 
   217 
   224     while (len != aLen)
   218     while (len != aLen)
   225         {
   219         {
   226         // handle residue
   220         // handle residue
   240 
   234 
   241         // write rest of the block
   235         // write rest of the block
   242         TInt err = iSbcInterface->Write10L(aPos/blockLen, buf, aOffset, len);
   236         TInt err = iSbcInterface->Write10L(aPos/blockLen, buf, aOffset, len);
   243         if (err)
   237         if (err)
   244             {
   238             {
   245             DoCheckConditionL();
   239             User::LeaveIfError(DoCheckConditionL());
   246             User::LeaveIfError(KErrAbort);
       
   247             }
   240             }
   248         }
   241         }
   249     }
   242     }
   250 
   243 
   251 
   244 
   266     do
   259     do
   267         {
   260         {
   268         err = iSbcInterface->ReadCapacity10L(lastLba, blockLength);
   261         err = iSbcInterface->ReadCapacity10L(lastLba, blockLength);
   269         } while (err == KErrCommandStalled && stallCounter-- > 0);
   262         } while (err == KErrCommandStalled && stallCounter-- > 0);
   270 
   263 
   271 
   264     if (err)
       
   265         {
       
   266         // DoCheckConditionL clears sense error
       
   267         // Media not present will return KErrNotReady so leave here
       
   268         User::LeaveIfError(DoCheckConditionL());
       
   269         }
       
   270 
       
   271     // update iWriteProtect
       
   272     err = MsModeSense10L();
   272     if (err)
   273     if (err)
   273         {
   274         {
   274         if (err == KErrCommandFailed)
   275         if (err == KErrCommandFailed)
   275             {
   276             {
   276             // Clear sense error
   277             // Clear sense error
   277             DoCheckConditionL();
   278             err = DoCheckConditionL();
   278             }
   279             // ignore error if unsupported
   279         User::LeaveIfError(KErrAbort);
   280             if (err != KErrUnknown)
   280         }
   281                 {
   281 
   282                 User::LeaveIfError(err);
   282     // update iWriteProtect
   283                 }
   283     err = MsModeSense10L();
       
   284     if (err)
       
   285         {
       
   286         if (err == KErrCommandFailed)
       
   287             {
       
   288             // Clear sense error
       
   289             DoCheckConditionL();
       
   290             }
   284             }
   291 
   285 
   292         err = MsModeSense6L();
   286         err = MsModeSense6L();
   293         if (err == KErrCommandFailed)
   287         if (err == KErrCommandFailed)
   294             {
   288             {
   295             // Clear sense error
   289             // Clear sense error
   296             DoCheckConditionL();
   290             err = DoCheckConditionL();
       
   291             // ignore error if unsupported
       
   292             if (err != KErrUnknown)
       
   293                 {
       
   294                 User::LeaveIfError(err);
       
   295                 }
   297             }           
   296             }           
   298         }
   297         }
   299 
   298 
   300     aCapsInfo.iNumberOfBlocks = lastLba + 1;
   299     aCapsInfo.iNumberOfBlocks = lastLba + 1;
   301     aCapsInfo.iBlockLength = blockLength;
   300     aCapsInfo.iBlockLength = blockLength;
   479 	__MSFNLOG
   478 	__MSFNLOG
   480     return iSpcInterface.PreventAllowMediumRemovalL(aPrevent);
   479     return iSpcInterface.PreventAllowMediumRemovalL(aPrevent);
   481     }
   480     }
   482 
   481 
   483 
   482 
   484 void CScsiProtocol::DoCheckConditionL()
   483 TInt CScsiProtocol::DoCheckConditionL()
   485     {
   484     {
   486 	__MSFNLOG
   485 	__MSFNLOG
   487     User::LeaveIfError(MsRequestSenseL());
   486     User::LeaveIfError(MsRequestSenseL());
       
   487 
       
   488     TInt err;
   488 
   489 
   489     // Check if init is needed
   490     // Check if init is needed
   490     if (iSenseInfo.iSenseCode == TSenseInfo::ENotReady &&
   491     if (iSenseInfo.iSenseCode == TSenseInfo::ENotReady &&
   491         iSenseInfo.iAdditional == TSenseInfo::EAscLogicalUnitNotReady &&
   492         iSenseInfo.iAdditional == TSenseInfo::EAscLogicalUnitNotReady &&
   492         iSenseInfo.iQualifier == TSenseInfo::EAscqInitializingCommandRequired)
   493         iSenseInfo.iQualifier == TSenseInfo::EAscqInitializingCommandRequired)
   493         {
   494         {
   494         // start unit
   495         // start unit
   495         TInt err = iSbcInterface->StartStopUnitL(ETrue);
   496         err = iSbcInterface->StartStopUnitL(ETrue);
   496 
       
   497         if (err)
   497         if (err)
   498             {
   498             {
   499             User::LeaveIfError(MsRequestSenseL());
   499             User::LeaveIfError(MsRequestSenseL());
   500             }
   500             }
   501 
   501         }
   502         }
   502 
   503 
   503     err = GetSystemWideSenseError(iSenseInfo);
   504     TInt r = GetSystemWideSenseError(iSenseInfo);
   504 
   505 
   505     TScsiState nextState = iState;
   506     if (((r == KErrNotReady) && (iState == EConnected)) ||
   506     if (err == KErrDisconnected)
   507         r == KErrDisconnected)
   507         {
   508 	    {
   508         nextState = EDisconnected;
   509         CompleteNotifyChangeL();
   509         }
   510         }
   510     else if (err == KErrNotReady)
       
   511         {
       
   512         nextState = EMediaNotPresent;
       
   513         }
       
   514     else
       
   515         {
       
   516         // no state change;
       
   517         }
       
   518 
       
   519     if (nextState != iState)
       
   520         {
       
   521         iMediaChangeNotifier.DoNotifyL();
       
   522         iState = nextState;
       
   523         }
       
   524            
       
   525     return err;
   511     }
   526     }
   512 
   527 
   513 
   528 
   514 /**
   529 /**
   515 Map SCSI sense error to a system wide error code
   530 Map SCSI sense error to a system wide error code
   728 void CScsiProtocol::DoScsiReadyCheckEventL()
   743 void CScsiProtocol::DoScsiReadyCheckEventL()
   729 	{
   744 	{
   730     __MSFNLOG
   745     __MSFNLOG
   731 	TInt err = KErrNone;
   746 	TInt err = KErrNone;
   732 
   747 
   733 	if(iFsm->IsRemovableMedia() || iState == EDisconnected)
   748 	if(iFsm->IsRemovableMedia() || iState != EConnected)
   734         {
   749         {
   735 		iFsm->SetStatusCheck();
   750 		iFsm->SetStatusCheck();
   736 		TRAP(err, iFsm->ConnectLogicalUnitL());
   751 		TRAP(err, iFsm->ConnectLogicalUnitL());
   737 		iFsm->ClearStatusCheck();
   752 		iFsm->ClearStatusCheck();
   738 
   753 
   758             iMediaChangeNotifier.DoNotifyL();
   773             iMediaChangeNotifier.DoNotifyL();
   759 			}
   774 			}
   760         }
   775         }
   761 	}
   776 	}
   762 
   777 
   763 void CScsiProtocol::CompleteNotifyChangeL()
       
   764 	{
       
   765     __MSFNLOG
       
   766     if (!iFsm->IsStatusCheck())
       
   767 		{
       
   768 		if (iState == EConnected)
       
   769 			{
       
   770 			iState = EDisconnected;
       
   771             iMediaChangeNotifier.DoNotifyL();
       
   772 			}
       
   773 		}
       
   774 	}
       
   775 
   778 
   776 RMediaChangeNotifier::RMediaChangeNotifier()
   779 RMediaChangeNotifier::RMediaChangeNotifier()
   777 :   iRegistered(EFalse)
   780 :   iRegistered(EFalse)
   778     {
   781     {
   779     __MSFNSLOG
   782     __MSFNSLOG