1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kerneltest/f32test/smassstorage/src/scsicmdbuilder.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,150 @@
1.4 +// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of the License "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// Provides utilities to build SCSI commands
1.18 +//
1.19 +//
1.20 +
1.21 +/**
1.22 + @file
1.23 + @internalTechnology
1.24 +*/
1.25 +
1.26 +#include <e32std.h>
1.27 +#include <e32std_private.h>
1.28 +#include <testusbc.h>
1.29 +#include "scsicmdbuilder.h"
1.30 +
1.31 +#define SCSI_READ_WRITE_LEN 10
1.32 +#define SCSI_UNIT_READY_LEN 6
1.33 +#define SCSI_MED_RMVL_LEN 6
1.34 +#define SCSI_START_STOP_LEN 6
1.35 +
1.36 +GLDEF_D TBuf8<KScsiCmdMaxLen> scsiCmdBuf;
1.37 +GLREF_D RDevTestUsbcClient usbcClient;
1.38 +
1.39 +void BuildReadWrite(TInt aFlag, TInt aLogicalBlkAddr, TInt aTotalBlks)
1.40 + //
1.41 + // Builds SCSI read(10) / write(10) command
1.42 + //
1.43 + {
1.44 + // Zero out the whole buffer
1.45 + scsiCmdBuf.FillZ(SCSI_READ_WRITE_LEN);
1.46 + scsiCmdBuf[0] = TUint8(aFlag); // opcode for read (0x28)/write (0x2A)
1.47 +
1.48 + // Fill in logical block address. Big endian
1.49 + scsiCmdBuf[2] = TUint8((aLogicalBlkAddr >> 24) & 0xFF);
1.50 + scsiCmdBuf[3] = TUint8((aLogicalBlkAddr >> 16) & 0xFF);
1.51 + scsiCmdBuf[4] = TUint8((aLogicalBlkAddr >> 8) & 0xFF);
1.52 + scsiCmdBuf[5] = TUint8(aLogicalBlkAddr & 0xFF);
1.53 +
1.54 + // Data transfer length (# of sectors). Big endian
1.55 + scsiCmdBuf[7] = TUint8((aTotalBlks >> 8) & 0xFF);
1.56 + scsiCmdBuf[8] = TUint8((aTotalBlks & 0xFF));
1.57 +
1.58 + scsiCmdBuf.SetLength(SCSI_READ_WRITE_LEN);
1.59 + }
1.60 +
1.61 +void BuildMediumRemoval(TInt aFlag)
1.62 + //
1.63 + // Builds prevent/allow medium removal command
1.64 + //
1.65 + {
1.66 + // Zero out the buf
1.67 + scsiCmdBuf.SetLength(SCSI_MED_RMVL_LEN);
1.68 + scsiCmdBuf.FillZ(SCSI_MED_RMVL_LEN);
1.69 + scsiCmdBuf[0] = 0x1E; // opcode for medium removal
1.70 + scsiCmdBuf[4] = TUint8(aFlag); // prevent(1)/allow(0) medium removal
1.71 + }
1.72 +
1.73 +void BuildTestUnitReady()
1.74 + //
1.75 + // Builds test unit ready command
1.76 + //
1.77 + {
1.78 + // Zero out the buf
1.79 + scsiCmdBuf.FillZ(SCSI_UNIT_READY_LEN);
1.80 + scsiCmdBuf[0] = 0; // opcode for test unit ready
1.81 +
1.82 + scsiCmdBuf.SetLength(SCSI_UNIT_READY_LEN);
1.83 + }
1.84 +
1.85 +void BuildStartStopUnit(TInt aFlag)
1.86 + //
1.87 + // Builds start/stop unit command
1.88 + //
1.89 + {
1.90 + const TUint8 KStartMask = 0x01;
1.91 + const TUint8 KLoejMask = 0x02;
1.92 + // Zero out the buf
1.93 + scsiCmdBuf.FillZ(SCSI_START_STOP_LEN);
1.94 + scsiCmdBuf[0] = 0x1B; // opcode for test unit ready
1.95 + scsiCmdBuf[1] = 0x01; // set immed bit to true
1.96 + scsiCmdBuf[4] = TUint8((aFlag == 1) ? KLoejMask & KStartMask : KLoejMask); // LOEJ + START or STOP
1.97 +
1.98 + scsiCmdBuf.SetLength(SCSI_START_STOP_LEN);
1.99 + }
1.100 +
1.101 +void fillInt(TUint8* dest, TInt source)
1.102 + //
1.103 + // Copy an int. Little endian
1.104 + //
1.105 + {
1.106 + for (TInt i = 0; i < 4; i++)
1.107 + {
1.108 + *dest++ = TUint8((source >> i*8) & 0xFF);
1.109 + }
1.110 + }
1.111 +
1.112 +TInt extractInt(const TUint8* aBuf)
1.113 + //
1.114 + // Extract an integer from a buffer. Assume little endian
1.115 + //
1.116 + {
1.117 + return aBuf[0] + (aBuf[1] << 8) + (aBuf[2] << 16) + (aBuf[3] << 24);
1.118 + }
1.119 +
1.120 +void createCBW(TDes8& aCbw, TInt aDCBWTag, TInt aDataTransferLen, TUint8 aInOutFlag, TDes8& aCBWCB, TUint8 aTestLun)
1.121 + //
1.122 + // aCbw: stores CBW
1.123 + // aDCBWTag: a command block tag sent by the host. Used to associates a CSW
1.124 + // with corresponding CBW
1.125 + // aDataTranferLen: the number of bytes the host expects to transfer
1.126 + // aInOutFlag: value for bmCBWFlags field, indicating the direction of transfer
1.127 + // aCBWCB the actual command to be wrapped
1.128 + // aTestLun local unit number
1.129 + {
1.130 + // Zero out aCbw
1.131 + aCbw.SetLength(KCbwLength);
1.132 + aCbw.FillZ();
1.133 +
1.134 + // dCBWSignature field, the value comes from spec
1.135 + TInt dCBWSignature = 0x43425355;
1.136 + fillInt(&aCbw[0], dCBWSignature);
1.137 + // dCBWTag field
1.138 + fillInt(&aCbw[4], aDCBWTag);
1.139 + // dCBWDataTransferLength field
1.140 + fillInt(&aCbw[8], aDataTransferLen);
1.141 + // bmCBWFlags field
1.142 + aCbw[12] = aInOutFlag;
1.143 + aCbw[13] = aTestLun;
1.144 + // bCBWCBLength field
1.145 + aCbw[14] = TUint8(aCBWCB.Length());
1.146 +
1.147 + // CBWCB field
1.148 + for (TInt i = 0; i < aCbw[14]; ++i)
1.149 + {
1.150 + aCbw[15 + i] = aCBWCB[i];
1.151 + }
1.152 + }
1.153 +