os/kernelhwsrv/userlibandfileserver/fileserver/shostmassstorage/server/protocol/cscsiprotocol.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of the License "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
//
sl@0
    15
sl@0
    16
/**
sl@0
    17
 @file
sl@0
    18
 @internalTechnology
sl@0
    19
*/
sl@0
    20
sl@0
    21
#include <e32base.h>
sl@0
    22
sl@0
    23
#include "debug.h"
sl@0
    24
#include "msdebug.h"
sl@0
    25
#include "msctypes.h"
sl@0
    26
#include "shared.h"
sl@0
    27
#include "msgservice.h"
sl@0
    28
sl@0
    29
#include "mscutils.h"
sl@0
    30
sl@0
    31
#include "mtransport.h"
sl@0
    32
#include "mprotocol.h"
sl@0
    33
#include "tscsiclientreq.h"
sl@0
    34
#include "tscsiprimarycmds.h"
sl@0
    35
#include "tscsiblockcmds.h"
sl@0
    36
sl@0
    37
#include "mblocktransferprotocol.h"
sl@0
    38
#include "tblocktransfer.h"
sl@0
    39
sl@0
    40
#include "tsbcclientinterface.h"
sl@0
    41
#include "tspcclientinterface.h"
sl@0
    42
#include "cmassstoragefsm.h"
sl@0
    43
#include "cscsiprotocol.h"
sl@0
    44
sl@0
    45
#include "usbmshostpanic.h"
sl@0
    46
sl@0
    47
sl@0
    48
sl@0
    49
/**
sl@0
    50
Create the CScsiProtocol object.
sl@0
    51
sl@0
    52
@param aLun The LUN for the device represented by this object
sl@0
    53
@param aTransport The transport interface
sl@0
    54
@param aStatusPollingInterval The polling interval
sl@0
    55
@return CScsiProtocol* A reference to the
sl@0
    56
*/
sl@0
    57
CScsiProtocol* CScsiProtocol::NewL(TLun aLun, MTransport& aTransport)
sl@0
    58
    {
sl@0
    59
	__MSFNSLOG
sl@0
    60
	CScsiProtocol* r = new (ELeave) CScsiProtocol(aTransport);
sl@0
    61
sl@0
    62
	CleanupStack::PushL(r);
sl@0
    63
	r->ConstructL(aLun);
sl@0
    64
	CleanupStack::Pop();
sl@0
    65
	return r;
sl@0
    66
    }
sl@0
    67
sl@0
    68
void CScsiProtocol::ConstructL(TLun aLun)
sl@0
    69
    {
sl@0
    70
	__MSFNLOG
sl@0
    71
    iFsm = CMassStorageFsm::NewL(*this);
sl@0
    72
	iState = EDisconnected;
sl@0
    73
sl@0
    74
    const TInt blockLength = 0x200;
sl@0
    75
sl@0
    76
    iHeadbuf.CreateL(blockLength);
sl@0
    77
    iTailbuf.CreateL(blockLength);
sl@0
    78
    }
sl@0
    79
sl@0
    80
sl@0
    81
CScsiProtocol::CScsiProtocol(MTransport& aTransport)
sl@0
    82
:   iSpcInterface(aTransport),
sl@0
    83
    iSbcInterface(NULL)
sl@0
    84
    {
sl@0
    85
	__MSFNLOG
sl@0
    86
    }
sl@0
    87
sl@0
    88
sl@0
    89
CScsiProtocol::~CScsiProtocol()
sl@0
    90
    {
sl@0
    91
	__MSFNLOG
sl@0
    92
    delete iFsm;
sl@0
    93
    iHeadbuf.Close();
sl@0
    94
    iTailbuf.Close();
sl@0
    95
    delete iSbcInterface;
sl@0
    96
    }
sl@0
    97
sl@0
    98
sl@0
    99
void CScsiProtocol::InitialiseUnitL()
sl@0
   100
    {
sl@0
   101
	__MSFNLOG
sl@0
   102
sl@0
   103
	// A device may take time to mount the media. If the device fails attempt to
sl@0
   104
	// retry the connection for a number of seconds
sl@0
   105
    TInt retryCounter = 20;
sl@0
   106
    do
sl@0
   107
        {
sl@0
   108
        retryCounter--;
sl@0
   109
        iFsm->ConnectLogicalUnitL();
sl@0
   110
        iState = iFsm->IsConnected() ? EConnected: EDisconnected;
sl@0
   111
sl@0
   112
        if (iState == EConnected)
sl@0
   113
            {
sl@0
   114
            break;
sl@0
   115
            }
sl@0
   116
        User::After(1000 * 200);    // 200 mS
sl@0
   117
        }
sl@0
   118
    while (retryCounter);
sl@0
   119
	}
sl@0
   120
sl@0
   121
sl@0
   122
void CScsiProtocol::UninitialiseUnitL()
sl@0
   123
    {
sl@0
   124
	__MSFNLOG
sl@0
   125
    iFsm->DisconnectLogicalUnitL();
sl@0
   126
    }
sl@0
   127
sl@0
   128
TBool CScsiProtocol::IsConnected()
sl@0
   129
    {
sl@0
   130
	__MSFNLOG
sl@0
   131
	return (iState == EConnected)? ETrue : EFalse;
sl@0
   132
    }
sl@0
   133
sl@0
   134
void CScsiProtocol::ReadL(TPos aPos,
sl@0
   135
                          TDes8& aBuf,
sl@0
   136
                          TInt aLength)
sl@0
   137
    {
sl@0
   138
	__MSFNLOG
sl@0
   139
    if(!IsConnected())
sl@0
   140
		User::Leave(KErrNotReady);
sl@0
   141
    iSbcInterface->iBlockTransfer.ReadL(*this, aPos, aLength, aBuf);
sl@0
   142
    }
sl@0
   143
sl@0
   144
sl@0
   145
void CScsiProtocol::BlockReadL(TPos aPos, TDes8& aCopybuf, TInt aLen)
sl@0
   146
    {
sl@0
   147
	__MSFNLOG
sl@0
   148
	__ASSERT_DEBUG(aPos % iSbcInterface->iBlockTransfer.BlockLength() == 0,
sl@0
   149
                   User::Panic(KUsbMsHostPanicCat, EBlockDevice));
sl@0
   150
sl@0
   151
    const TInt blockLen = iSbcInterface->iBlockTransfer.BlockLength();
sl@0
   152
    TInt len = aLen;
sl@0
   153
sl@0
   154
    TInt64 lba = aPos / static_cast<TInt64>(blockLen);
sl@0
   155
sl@0
   156
    if (I64HIGH(lba))
sl@0
   157
        {
sl@0
   158
        User::LeaveIfError(KErrOverflow);
sl@0
   159
        }
sl@0
   160
sl@0
   161
	TInt err = iSbcInterface->Read10L(I64LOW(lba), aCopybuf, len);
sl@0
   162
    if (err)
sl@0
   163
        {
sl@0
   164
        __SCSIPRINT1(_L("READ(10) Err=%d"), err);
sl@0
   165
        DoCheckConditionL();
sl@0
   166
        User::LeaveIfError(KErrAbort);
sl@0
   167
        }
sl@0
   168
sl@0
   169
    // handle residue
sl@0
   170
    while (len != aLen)
sl@0
   171
        {
sl@0
   172
        __SCSIPRINT2(_L("SCSI Read Residue 0x%x bytes read (0x%x)"), len, aLen);
sl@0
   173
        __SCSIPRINT2(_L("Pos=0x%lx Len=0x%x"), aPos, aLen);
sl@0
   174
sl@0
   175
        // read next block
sl@0
   176
sl@0
   177
        // full blocks read in bytes
sl@0
   178
        TInt bytesRead = len/blockLen * blockLen;
sl@0
   179
        aPos += bytesRead;
sl@0
   180
        aLen -= bytesRead;
sl@0
   181
        len = aLen;
sl@0
   182
sl@0
   183
        __SCSIPRINT3(_L("New Pos=0x%lx Len=0x%x (bytes read = %x)"),
sl@0
   184
                     aPos, aLen, bytesRead);
sl@0
   185
sl@0
   186
        aCopybuf.SetLength(bytesRead);
sl@0
   187
sl@0
   188
        // read rest of the block
sl@0
   189
        TInt err = iSbcInterface->Read10L(aPos/blockLen, aCopybuf, len);
sl@0
   190
        if (err)
sl@0
   191
            {
sl@0
   192
            DoCheckConditionL();
sl@0
   193
            User::LeaveIfError(KErrAbort);
sl@0
   194
            }
sl@0
   195
        }
sl@0
   196
    }
sl@0
   197
sl@0
   198
sl@0
   199
void CScsiProtocol::WriteL(TPos aPosition,
sl@0
   200
                           TDesC8& aBuf,
sl@0
   201
                           TInt aLength)
sl@0
   202
    {
sl@0
   203
	__MSFNLOG
sl@0
   204
    if(!IsConnected())
sl@0
   205
		User::Leave(KErrNotReady);
sl@0
   206
    iSbcInterface->iBlockTransfer.WriteL(*this, aPosition, aLength, aBuf);
sl@0
   207
    }
sl@0
   208
sl@0
   209
sl@0
   210
void CScsiProtocol::BlockWriteL(TPos aPos, TDesC8& aCopybuf, TUint aOffset, TInt aLen)
sl@0
   211
    {
sl@0
   212
	__MSFNLOG
sl@0
   213
	__ASSERT_DEBUG(aPos % iSbcInterface->iBlockTransfer.BlockLength() == 0,
sl@0
   214
                   User::Panic(KUsbMsHostPanicCat, EBlockDevice));
sl@0
   215
    const TInt blockLen = iSbcInterface->iBlockTransfer.BlockLength();
sl@0
   216
    TInt len = aLen;
sl@0
   217
	TInt err = iSbcInterface->Write10L(aPos/blockLen, aCopybuf, aOffset, len);
sl@0
   218
    if (err)
sl@0
   219
        {
sl@0
   220
        DoCheckConditionL();
sl@0
   221
        User::LeaveIfError(KErrAbort);
sl@0
   222
        }
sl@0
   223
sl@0
   224
    while (len != aLen)
sl@0
   225
        {
sl@0
   226
        // handle residue
sl@0
   227
        __SCSIPRINT2(_L("SCSI Write Residue 0x%x bytes read (0x%x)"), len, aLen);
sl@0
   228
        __SCSIPRINT2(_L("Pos=0x%lx Len=0x%x"), aPos, aLen);
sl@0
   229
sl@0
   230
        // write next block
sl@0
   231
sl@0
   232
        // full blocks written in bytes
sl@0
   233
        TInt bytesWritten = len/blockLen * blockLen;
sl@0
   234
        aPos += bytesWritten;
sl@0
   235
        aLen -= bytesWritten;
sl@0
   236
        len = aLen;
sl@0
   237
        __SCSIPRINT2(_L("New Pos=0x%lx Len=0x%x"), aPos, aLen);
sl@0
   238
sl@0
   239
        TPtrC8 buf = aCopybuf.Mid(bytesWritten);
sl@0
   240
sl@0
   241
        // write rest of the block
sl@0
   242
        TInt err = iSbcInterface->Write10L(aPos/blockLen, buf, aOffset, len);
sl@0
   243
        if (err)
sl@0
   244
            {
sl@0
   245
            DoCheckConditionL();
sl@0
   246
            User::LeaveIfError(KErrAbort);
sl@0
   247
            }
sl@0
   248
        }
sl@0
   249
    }
sl@0
   250
sl@0
   251
sl@0
   252
void CScsiProtocol::GetCapacityL(TCapsInfo& aCapsInfo)
sl@0
   253
    {
sl@0
   254
	__MSFNLOG
sl@0
   255
    if (!IsConnected())
sl@0
   256
        {
sl@0
   257
        DoScsiReadyCheckEventL();
sl@0
   258
        }
sl@0
   259
sl@0
   260
	TLba lastLba;
sl@0
   261
	TUint32 blockLength;
sl@0
   262
sl@0
   263
    // Retry ReadCapacity10L if stalled
sl@0
   264
    TInt stallCounter = 4;
sl@0
   265
    TInt err = KErrNone;
sl@0
   266
    do
sl@0
   267
        {
sl@0
   268
        err = iSbcInterface->ReadCapacity10L(lastLba, blockLength);
sl@0
   269
        } while (err == KErrCommandStalled && stallCounter-- > 0);
sl@0
   270
sl@0
   271
sl@0
   272
    if (err)
sl@0
   273
        {
sl@0
   274
        if (err == KErrCommandFailed)
sl@0
   275
            {
sl@0
   276
            // Clear sense error
sl@0
   277
            DoCheckConditionL();
sl@0
   278
            }
sl@0
   279
        User::LeaveIfError(KErrAbort);
sl@0
   280
        }
sl@0
   281
sl@0
   282
    // update iWriteProtect
sl@0
   283
    err = MsModeSense10L();
sl@0
   284
    if (err)
sl@0
   285
        {
sl@0
   286
        if (err == KErrCommandFailed)
sl@0
   287
            {
sl@0
   288
            // Clear sense error
sl@0
   289
            DoCheckConditionL();
sl@0
   290
            }
sl@0
   291
sl@0
   292
        err = MsModeSense6L();
sl@0
   293
        if (err == KErrCommandFailed)
sl@0
   294
            {
sl@0
   295
            // Clear sense error
sl@0
   296
            DoCheckConditionL();
sl@0
   297
            }           
sl@0
   298
        }
sl@0
   299
sl@0
   300
    aCapsInfo.iNumberOfBlocks = lastLba + 1;
sl@0
   301
    aCapsInfo.iBlockLength = blockLength;
sl@0
   302
    aCapsInfo.iWriteProtect = iWriteProtect;
sl@0
   303
sl@0
   304
	__SCSIPRINT3(_L("numBlock = x%x , blockLength = %x wp = %d"),
sl@0
   305
                 lastLba + 1, blockLength, iWriteProtect);
sl@0
   306
    }
sl@0
   307
sl@0
   308
sl@0
   309
/**
sl@0
   310
Perform SCSI INQUIRY command. The function leaves if the device response is not
sl@0
   311
compliant with the protocol standard.
sl@0
   312
sl@0
   313
@return TInt KErrNone if successful otherwise KErrCommandFailed to indicate a
sl@0
   314
device status error
sl@0
   315
*/
sl@0
   316
TInt CScsiProtocol::MsInquiryL()
sl@0
   317
    {
sl@0
   318
	__MSFNLOG
sl@0
   319
    ResetSbc();
sl@0
   320
sl@0
   321
   /**
sl@0
   322
    INQUIRY
sl@0
   323
   */
sl@0
   324
sl@0
   325
   /**
sl@0
   326
    SPC states
sl@0
   327
    - the INQUIRY data should be returned even though the device server is not
sl@0
   328
      ready for other commands.
sl@0
   329
sl@0
   330
    - If the standard INQUIRY data changes for any reason, the device server
sl@0
   331
      shall generate a unit attention condition
sl@0
   332
   */
sl@0
   333
    TPeripheralInfo info;
sl@0
   334
    TInt err = iSpcInterface.InquiryL(info);
sl@0
   335
    if (err)
sl@0
   336
        {
sl@0
   337
        // KErrCommandFailed
sl@0
   338
        return err;
sl@0
   339
        }
sl@0
   340
sl@0
   341
    // print reponse
sl@0
   342
    __TESTREPORT1(_L("RMB = %d"), info.iRemovable);
sl@0
   343
    __TESTREPORT2(_L("PERIPHERAL DEVICE TYPE = %d PQ = %d"),
sl@0
   344
                 info.iPeripheralDeviceType,
sl@0
   345
                 info.iPeripheralQualifier);
sl@0
   346
    __TESTREPORT1(_L("VERSION = %d"), info.iVersion);
sl@0
   347
    __TESTREPORT1(_L("RESPONSE DATA FORMAT = %d"), info.iResponseDataFormat);
sl@0
   348
    __TESTREPORT3(_L("VENDOR ID %S PRODUCT ID %S REV %S"),
sl@0
   349
                 &info.iIdentification.iVendorId,
sl@0
   350
                 &info.iIdentification.iProductId,
sl@0
   351
                 &info.iIdentification.iProductRev);
sl@0
   352
sl@0
   353
    if (info.iPeripheralQualifier != 0 && info.iPeripheralQualifier != 1)
sl@0
   354
        {
sl@0
   355
        __HOSTPRINT(_L("Peripheral Qualifier[Unknown device type]\n"))
sl@0
   356
        return KErrNotSupported;
sl@0
   357
        }
sl@0
   358
sl@0
   359
    if (info.iPeripheralDeviceType != 0)
sl@0
   360
        {
sl@0
   361
        __HOSTPRINT(_L("Peripheral Device Type[Unsupported device type]\n"))
sl@0
   362
        return KErrNotSupported;
sl@0
   363
        }
sl@0
   364
sl@0
   365
    iRemovableMedia = info.iRemovable;
sl@0
   366
sl@0
   367
    // SCSI Block device
sl@0
   368
    iSbcInterface = new (ELeave) TSbcClientInterface(iSpcInterface.Transport());
sl@0
   369
    iSbcInterface->InitBuffers(&iHeadbuf, &iTailbuf);
sl@0
   370
sl@0
   371
    return KErrNone;
sl@0
   372
    }
sl@0
   373
sl@0
   374
sl@0
   375
/**
sl@0
   376
Perform SCSI TEST UNIT READY command. The function leaves if the device response
sl@0
   377
is not compliant with the protocol standard.
sl@0
   378
sl@0
   379
@return TInt KErrNone if successful or otherwise KErrCommandFailed to indicate a
sl@0
   380
device status error
sl@0
   381
*/
sl@0
   382
TInt CScsiProtocol::MsTestUnitReadyL()
sl@0
   383
    {
sl@0
   384
	__MSFNLOG
sl@0
   385
    /* TestUnitReady */
sl@0
   386
    return iSpcInterface.TestUnitReadyL();
sl@0
   387
    }
sl@0
   388
sl@0
   389
sl@0
   390
/**
sl@0
   391
Perform SCSI READ CAPACITY (10) command. The function leaves if the device
sl@0
   392
response is not compliant with the protocol standard.
sl@0
   393
sl@0
   394
Before a block device can be read or written the media's capacity (LAST LBA and
sl@0
   395
BLOCK SIZE) must be obtained. This function is used to initialise TBlockTransfer
sl@0
   396
with the capacity parameters via TSbcInterface::ReadCapcaityL().
sl@0
   397
sl@0
   398
@return TInt KErrNone if successful, KErrCommandFailed to indicate a
sl@0
   399
device status error, KErrCommandStalled to indicate a device stall
sl@0
   400
*/
sl@0
   401
TInt CScsiProtocol::MsReadCapacityL()
sl@0
   402
    {
sl@0
   403
	__MSFNLOG
sl@0
   404
    // READ CAPACITY
sl@0
   405
    TUint32 blockSize;
sl@0
   406
    TUint32 lastLba;
sl@0
   407
    TInt err = iSbcInterface->ReadCapacity10L(lastLba, blockSize);
sl@0
   408
sl@0
   409
    __TESTREPORT2(_L("CAPACITY: Block Size=0x%x Last LBA=0x%x"), blockSize, lastLba);
sl@0
   410
    return err;
sl@0
   411
    }
sl@0
   412
sl@0
   413
sl@0
   414
/**
sl@0
   415
Perform MODE SENSE (10) command. The function leaves if the device response is
sl@0
   416
not compliant with the protocol standard.
sl@0
   417
sl@0
   418
@return TInt KErrNone if successful, KErrCommandFailed to indicate a
sl@0
   419
device status error, KErrCommandStalled to indicate a device stall
sl@0
   420
*/
sl@0
   421
TInt CScsiProtocol::MsModeSense10L()
sl@0
   422
    {
sl@0
   423
	__MSFNLOG
sl@0
   424
    TBool writeProtected;
sl@0
   425
    TInt err = iSbcInterface->ModeSense10L(TSbcClientInterface::EReturnAllModePages, writeProtected);
sl@0
   426
sl@0
   427
    if (!err)
sl@0
   428
        {
sl@0
   429
        iWriteProtect = writeProtected;
sl@0
   430
        }
sl@0
   431
    return err;
sl@0
   432
    }
sl@0
   433
sl@0
   434
sl@0
   435
/**
sl@0
   436
Perform SCSI MODE SENSE (6) command. The function leaves if the device response
sl@0
   437
is not compliant with the protocol standard.
sl@0
   438
sl@0
   439
@return TInt KErrNone if successful, KErrCommandFailed to indicate a
sl@0
   440
device status error, KErrCommandStalled to indicate a device stall
sl@0
   441
*/
sl@0
   442
TInt CScsiProtocol::MsModeSense6L()
sl@0
   443
    {
sl@0
   444
	__MSFNLOG
sl@0
   445
    TBool writeProtected;
sl@0
   446
    TInt err = iSbcInterface->ModeSense6L(TSbcClientInterface::EReturnAllModePages, writeProtected);
sl@0
   447
sl@0
   448
    if (!err)
sl@0
   449
        {
sl@0
   450
        iWriteProtect = writeProtected;
sl@0
   451
        }
sl@0
   452
    return err;
sl@0
   453
    }
sl@0
   454
sl@0
   455
sl@0
   456
/**
sl@0
   457
Perform SCSI START STOP UNIT command. The function leaves if the device response
sl@0
   458
is not compliant with the protocol standard.
sl@0
   459
sl@0
   460
@return TInt KErrNone if successful otherwise KErrCommandFailed to indicate a
sl@0
   461
device status error
sl@0
   462
*/
sl@0
   463
TInt CScsiProtocol::MsStartStopUnitL(TBool aStart)
sl@0
   464
    {
sl@0
   465
	__MSFNLOG
sl@0
   466
    return iSbcInterface->StartStopUnitL(aStart);
sl@0
   467
    }
sl@0
   468
sl@0
   469
sl@0
   470
/**
sl@0
   471
Perform SCSI PREVENT ALLOW MEDIA REMOVAL command. The function leaves if the
sl@0
   472
device response is not compliant with the protocol standard.
sl@0
   473
sl@0
   474
@return TInt KErrNone if successful otherwise KErrCommandFailed to indicate a
sl@0
   475
device status error
sl@0
   476
*/
sl@0
   477
TInt CScsiProtocol::MsPreventAllowMediaRemovalL(TBool aPrevent)
sl@0
   478
    {
sl@0
   479
	__MSFNLOG
sl@0
   480
    return iSpcInterface.PreventAllowMediumRemovalL(aPrevent);
sl@0
   481
    }
sl@0
   482
sl@0
   483
sl@0
   484
void CScsiProtocol::DoCheckConditionL()
sl@0
   485
    {
sl@0
   486
	__MSFNLOG
sl@0
   487
    User::LeaveIfError(MsRequestSenseL());
sl@0
   488
sl@0
   489
    // Check if init is needed
sl@0
   490
    if (iSenseInfo.iSenseCode == TSenseInfo::ENotReady &&
sl@0
   491
        iSenseInfo.iAdditional == TSenseInfo::EAscLogicalUnitNotReady &&
sl@0
   492
        iSenseInfo.iQualifier == TSenseInfo::EAscqInitializingCommandRequired)
sl@0
   493
        {
sl@0
   494
        // start unit
sl@0
   495
        TInt err = iSbcInterface->StartStopUnitL(ETrue);
sl@0
   496
sl@0
   497
        if (err)
sl@0
   498
            {
sl@0
   499
            User::LeaveIfError(MsRequestSenseL());
sl@0
   500
            }
sl@0
   501
sl@0
   502
        }
sl@0
   503
sl@0
   504
    TInt r = GetSystemWideSenseError(iSenseInfo);
sl@0
   505
sl@0
   506
    if (((r == KErrNotReady) && (iState == EConnected)) ||
sl@0
   507
        r == KErrDisconnected)
sl@0
   508
	    {
sl@0
   509
        CompleteNotifyChangeL();
sl@0
   510
        }
sl@0
   511
    }
sl@0
   512
sl@0
   513
sl@0
   514
/**
sl@0
   515
Map SCSI sense error to a system wide error code
sl@0
   516
KErrNotReady could happen due to any of the following reasons:
sl@0
   517
    1. Lun is in the process of becoming ready
sl@0
   518
    2. Initialising command is required
sl@0
   519
    3. Lun is not ready to process the command - meaning it is still handling
sl@0
   520
    the previous command
sl@0
   521
sl@0
   522
KErrUnknown could happen due to any of the following reasons:
sl@0
   523
    1. Mass storage device does not respond to the selected logical unit, other
sl@0
   524
    than the locial unit not ready scenario 2. The command sent was not
sl@0
   525
    recognized or contains a invalid code 3. Invialid field in the command block
sl@0
   526
    4. The requested logical unit is not supported
sl@0
   527
    5. The mass storage device cnosists of insufficient resource
sl@0
   528
    6. Hardware error
sl@0
   529
    7. Blank check
sl@0
   530
    8. Vendor specific error
sl@0
   531
    9. Any illegal request (we assume the commands sent by MSC should be
sl@0
   532
    supported by the device, if not then the illegal request is said to be of
sl@0
   533
    unknown system wide error for Symbian. 10. Miscompare - we do not support
sl@0
   534
    the compare operation/command so this error should not happen
sl@0
   535
sl@0
   536
KErrAccessDenied could happen due to any of the following reasons:
sl@0
   537
    1. Data protection error happened
sl@0
   538
    2. Media was write protected
sl@0
   539
    3. Media was not present
sl@0
   540
sl@0
   541
KErrOverflow could happen due to any of the following reasons:
sl@0
   542
    1. Data over flow occured
sl@0
   543
    2. The requested LBA is out of range
sl@0
   544
sl@0
   545
KErrAbort could happen due to any of the following reasons:
sl@0
   546
    1. A copy operation is aborted.
sl@0
   547
    2. The command is aborted
sl@0
   548
sl@0
   549
KErrCorrupt could happen due to any of the following reasons:
sl@0
   550
    1. The underlying media was having errors
sl@0
   551
sl@0
   552
KErrDisconnected could happen due to any of the following reasons:
sl@0
   553
    1. The media was changed/removed - While this error is happening the file
sl@0
   554
    extension will be notified setting the iChanged flag
sl@0
   555
*/
sl@0
   556
TInt CScsiProtocol::GetSystemWideSenseError(const TSenseInfo& aSenseInfo)
sl@0
   557
	{
sl@0
   558
	__MSFNLOG
sl@0
   559
	TInt ret = KErrNone;
sl@0
   560
	TInt additionalError = KErrNone;
sl@0
   561
sl@0
   562
	switch(aSenseInfo.iSenseCode)
sl@0
   563
		{
sl@0
   564
		case TSenseInfo::ENoSense:
sl@0
   565
		case TSenseInfo::ERecoveredError:
sl@0
   566
			ret = KErrNone;
sl@0
   567
			break;
sl@0
   568
		case TSenseInfo::ENotReady:
sl@0
   569
            ret = KErrNotReady;
sl@0
   570
			additionalError = ProcessAsCodes(aSenseInfo);
sl@0
   571
            if (additionalError != KErrNone)
sl@0
   572
                {
sl@0
   573
                ret = additionalError;
sl@0
   574
                }
sl@0
   575
			break;
sl@0
   576
		case TSenseInfo::EMediumError:
sl@0
   577
			ret = KErrCorrupt;
sl@0
   578
			additionalError = ProcessAsCodes(aSenseInfo);
sl@0
   579
            if (additionalError != KErrNone)
sl@0
   580
                {
sl@0
   581
                ret = additionalError;
sl@0
   582
                }
sl@0
   583
			break;
sl@0
   584
		case TSenseInfo::EUnitAttention:
sl@0
   585
			ret = KErrDisconnected;
sl@0
   586
			break;
sl@0
   587
		case TSenseInfo::EDataProtection:
sl@0
   588
			ret = KErrAccessDenied;
sl@0
   589
			break;
sl@0
   590
		case TSenseInfo::EIllegalRequest:
sl@0
   591
		case TSenseInfo::EHardwareError:
sl@0
   592
		case TSenseInfo::EBlankCheck:
sl@0
   593
		case TSenseInfo::EVendorSpecific:
sl@0
   594
		case TSenseInfo::EMisCompare:
sl@0
   595
			ret = KErrUnknown;
sl@0
   596
			break;
sl@0
   597
		case TSenseInfo::ECopyAborted:
sl@0
   598
		case TSenseInfo::EAbortedCommand:
sl@0
   599
			ret = KErrAbort;
sl@0
   600
			break;
sl@0
   601
		case TSenseInfo::EDataOverflow:
sl@0
   602
			ret = KErrOverflow;
sl@0
   603
			break;
sl@0
   604
		default:
sl@0
   605
			ret = KErrUnknown;
sl@0
   606
			break;
sl@0
   607
		}
sl@0
   608
sl@0
   609
	return ret;
sl@0
   610
	}
sl@0
   611
sl@0
   612
sl@0
   613
TInt CScsiProtocol::ProcessAsCodes(const TSenseInfo& aSenseInfo)
sl@0
   614
    {
sl@0
   615
	__MSFNLOG
sl@0
   616
	TInt ret = KErrNone;
sl@0
   617
sl@0
   618
	switch(aSenseInfo.iAdditional)
sl@0
   619
		{
sl@0
   620
        case TSenseInfo::EAscLogicalUnitNotReady:
sl@0
   621
		case TSenseInfo::EMediaNotPresent:
sl@0
   622
            ret = KErrNotReady;
sl@0
   623
			break;
sl@0
   624
sl@0
   625
		case TSenseInfo::ELbaOutOfRange:
sl@0
   626
			ret = KErrOverflow;
sl@0
   627
			break;
sl@0
   628
sl@0
   629
		case TSenseInfo::EWriteProtected:
sl@0
   630
			ret = KErrAccessDenied;
sl@0
   631
			break;
sl@0
   632
sl@0
   633
		case TSenseInfo::ENotReadyToReadyChange:
sl@0
   634
			ret = KErrNone;
sl@0
   635
			break;
sl@0
   636
sl@0
   637
		case TSenseInfo::EAscLogicalUnitDoesNotRespondToSelection:
sl@0
   638
		case TSenseInfo::EInvalidCmdCode:
sl@0
   639
		case TSenseInfo::EInvalidFieldInCdb:
sl@0
   640
		case TSenseInfo::ELuNotSupported:
sl@0
   641
        case TSenseInfo::EInsufficientRes:
sl@0
   642
            ret = KErrUnknown;
sl@0
   643
            break;
sl@0
   644
		default:
sl@0
   645
			ret = KErrNone;
sl@0
   646
			break;
sl@0
   647
		}
sl@0
   648
	return ret;
sl@0
   649
	}
sl@0
   650
sl@0
   651
sl@0
   652
/**
sl@0
   653
Perform SCSI REQUEST SENSE command.  The function leaves if the device response
sl@0
   654
is not compliant with the protocol standard.
sl@0
   655
sl@0
   656
@return TInt KErrNone if successful otherwise KErrCommandFailed to indicate a
sl@0
   657
device status error
sl@0
   658
*/
sl@0
   659
TInt CScsiProtocol::MsRequestSenseL()
sl@0
   660
    {
sl@0
   661
	__MSFNLOG
sl@0
   662
    return iSpcInterface.RequestSenseL(iSenseInfo) ? KErrCommandFailed : KErrNone;
sl@0
   663
	}
sl@0
   664
sl@0
   665
sl@0
   666
void CScsiProtocol::CreateSbcInterfaceL(TUint32 aBlockLen, TUint32 aLastLba)
sl@0
   667
    {
sl@0
   668
	__MSFNLOG
sl@0
   669
    // SCSI Block device
sl@0
   670
    ASSERT(iSbcInterface == NULL);
sl@0
   671
    iSbcInterface = new (ELeave) TSbcClientInterface(iSpcInterface.Transport());
sl@0
   672
    iSbcInterface->InitBuffers(&iHeadbuf, &iTailbuf);
sl@0
   673
    iSbcInterface->SetCapacityL(aBlockLen, aLastLba);
sl@0
   674
    }
sl@0
   675
sl@0
   676
sl@0
   677
void CScsiProtocol::ResetSbc()
sl@0
   678
    {
sl@0
   679
	__MSFNLOG
sl@0
   680
    if (iSbcInterface)
sl@0
   681
        {
sl@0
   682
        delete iSbcInterface;
sl@0
   683
        iSbcInterface = NULL;
sl@0
   684
        }
sl@0
   685
    }
sl@0
   686
sl@0
   687
sl@0
   688
void CScsiProtocol::NotifyChange(const RMessage2& aMessage)
sl@0
   689
	{
sl@0
   690
    __MSFNLOG
sl@0
   691
    iMediaChangeNotifier.Register(aMessage);
sl@0
   692
	}
sl@0
   693
sl@0
   694
sl@0
   695
void CScsiProtocol::ForceCompleteNotifyChangeL()
sl@0
   696
	{
sl@0
   697
    __MSFNLOG
sl@0
   698
    iMediaChangeNotifier.DoNotifyL();
sl@0
   699
	}
sl@0
   700
sl@0
   701
sl@0
   702
void CScsiProtocol::CancelChangeNotifierL()
sl@0
   703
	{
sl@0
   704
    __MSFNLOG
sl@0
   705
    iMediaChangeNotifier.DoCancelL();
sl@0
   706
	}
sl@0
   707
sl@0
   708
sl@0
   709
void CScsiProtocol::SuspendL()
sl@0
   710
	{
sl@0
   711
    __MSFNLOG
sl@0
   712
    if (iFsm->StartStopUnitRequired())
sl@0
   713
        {
sl@0
   714
        iSbcInterface->StartStopUnitL(EFalse);
sl@0
   715
        }
sl@0
   716
	}
sl@0
   717
sl@0
   718
void CScsiProtocol::ResumeL()
sl@0
   719
	{
sl@0
   720
    __MSFNLOG
sl@0
   721
    if (iFsm->StartStopUnitRequired())
sl@0
   722
        {
sl@0
   723
        iSbcInterface->StartStopUnitL(ETrue);
sl@0
   724
        }
sl@0
   725
	}
sl@0
   726
sl@0
   727
sl@0
   728
void CScsiProtocol::DoScsiReadyCheckEventL()
sl@0
   729
	{
sl@0
   730
    __MSFNLOG
sl@0
   731
	TInt err = KErrNone;
sl@0
   732
sl@0
   733
	if(iFsm->IsRemovableMedia() || iState == EDisconnected)
sl@0
   734
        {
sl@0
   735
		iFsm->SetStatusCheck();
sl@0
   736
		TRAP(err, iFsm->ConnectLogicalUnitL());
sl@0
   737
		iFsm->ClearStatusCheck();
sl@0
   738
sl@0
   739
		User::LeaveIfError(err);
sl@0
   740
		err = iFsm->IsConnected() ? KErrNone : KErrNotReady;
sl@0
   741
        }
sl@0
   742
sl@0
   743
	if (iState == EConnected)
sl@0
   744
        {
sl@0
   745
		if (err != KErrNone)
sl@0
   746
			{
sl@0
   747
			iState = EDisconnected;
sl@0
   748
            __SCSIPRINT(_L("** Disconnected Notification **"));
sl@0
   749
            iMediaChangeNotifier.DoNotifyL();
sl@0
   750
			}
sl@0
   751
        }
sl@0
   752
	else
sl@0
   753
        {
sl@0
   754
		if (err == KErrNone)
sl@0
   755
			{
sl@0
   756
			iState = EConnected;
sl@0
   757
            __SCSIPRINT(_L("** Connected Notification **"));
sl@0
   758
            iMediaChangeNotifier.DoNotifyL();
sl@0
   759
			}
sl@0
   760
        }
sl@0
   761
	}
sl@0
   762
sl@0
   763
void CScsiProtocol::CompleteNotifyChangeL()
sl@0
   764
	{
sl@0
   765
    __MSFNLOG
sl@0
   766
    if (!iFsm->IsStatusCheck())
sl@0
   767
		{
sl@0
   768
		if (iState == EConnected)
sl@0
   769
			{
sl@0
   770
			iState = EDisconnected;
sl@0
   771
            iMediaChangeNotifier.DoNotifyL();
sl@0
   772
			}
sl@0
   773
		}
sl@0
   774
	}
sl@0
   775
sl@0
   776
RMediaChangeNotifier::RMediaChangeNotifier()
sl@0
   777
:   iRegistered(EFalse)
sl@0
   778
    {
sl@0
   779
    __MSFNSLOG
sl@0
   780
    }
sl@0
   781
sl@0
   782
sl@0
   783
RMediaChangeNotifier::~RMediaChangeNotifier()
sl@0
   784
    {
sl@0
   785
    __MSFNSLOG
sl@0
   786
    if (iRegistered)
sl@0
   787
        iNotifier.Complete(KErrDisconnected);
sl@0
   788
    }
sl@0
   789
sl@0
   790
/**
sl@0
   791
Initialise notifier to enable media change notfications.
sl@0
   792
sl@0
   793
@param aMessage The message to commplete the notification
sl@0
   794
*/
sl@0
   795
void RMediaChangeNotifier::Register(const RMessage2& aMessage)
sl@0
   796
    {
sl@0
   797
    __MSFNLOG
sl@0
   798
	iRegistered = ETrue;
sl@0
   799
	iNotifier = aMessage;
sl@0
   800
    }
sl@0
   801
sl@0
   802
sl@0
   803
void RMediaChangeNotifier::DoNotifyL()
sl@0
   804
    {
sl@0
   805
	__MSFNLOG
sl@0
   806
	CompleteNotifierL(KErrNone);
sl@0
   807
    }
sl@0
   808
sl@0
   809
void RMediaChangeNotifier::DoCancelL()
sl@0
   810
    {
sl@0
   811
	__MSFNLOG
sl@0
   812
	CompleteNotifierL(KErrCancel);
sl@0
   813
    }
sl@0
   814
sl@0
   815
void RMediaChangeNotifier::CompleteNotifierL(TInt aReason)
sl@0
   816
	{
sl@0
   817
    __MSFNLOG
sl@0
   818
	if (iRegistered)
sl@0
   819
        {
sl@0
   820
		TBool mediaChanged = ETrue;
sl@0
   821
		TPtrC8 pStatus((TUint8*)&mediaChanged,sizeof(TBool));
sl@0
   822
		iNotifier.WriteL(0,pStatus);
sl@0
   823
		iNotifier.Complete(aReason);
sl@0
   824
		iRegistered = EFalse;
sl@0
   825
        }
sl@0
   826
	}