diff -r 000000000000 -r bde4ae8d615e os/kernelhwsrv/kerneltest/f32test/smassstorage/src/scsicmdbuilder.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/os/kernelhwsrv/kerneltest/f32test/smassstorage/src/scsicmdbuilder.cpp Fri Jun 15 03:10:57 2012 +0200 @@ -0,0 +1,150 @@ +// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the License "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// Provides utilities to build SCSI commands +// +// + +/** + @file + @internalTechnology +*/ + +#include +#include +#include +#include "scsicmdbuilder.h" + +#define SCSI_READ_WRITE_LEN 10 +#define SCSI_UNIT_READY_LEN 6 +#define SCSI_MED_RMVL_LEN 6 +#define SCSI_START_STOP_LEN 6 + +GLDEF_D TBuf8 scsiCmdBuf; +GLREF_D RDevTestUsbcClient usbcClient; + +void BuildReadWrite(TInt aFlag, TInt aLogicalBlkAddr, TInt aTotalBlks) + // + // Builds SCSI read(10) / write(10) command + // + { + // Zero out the whole buffer + scsiCmdBuf.FillZ(SCSI_READ_WRITE_LEN); + scsiCmdBuf[0] = TUint8(aFlag); // opcode for read (0x28)/write (0x2A) + + // Fill in logical block address. Big endian + scsiCmdBuf[2] = TUint8((aLogicalBlkAddr >> 24) & 0xFF); + scsiCmdBuf[3] = TUint8((aLogicalBlkAddr >> 16) & 0xFF); + scsiCmdBuf[4] = TUint8((aLogicalBlkAddr >> 8) & 0xFF); + scsiCmdBuf[5] = TUint8(aLogicalBlkAddr & 0xFF); + + // Data transfer length (# of sectors). Big endian + scsiCmdBuf[7] = TUint8((aTotalBlks >> 8) & 0xFF); + scsiCmdBuf[8] = TUint8((aTotalBlks & 0xFF)); + + scsiCmdBuf.SetLength(SCSI_READ_WRITE_LEN); + } + +void BuildMediumRemoval(TInt aFlag) + // + // Builds prevent/allow medium removal command + // + { + // Zero out the buf + scsiCmdBuf.SetLength(SCSI_MED_RMVL_LEN); + scsiCmdBuf.FillZ(SCSI_MED_RMVL_LEN); + scsiCmdBuf[0] = 0x1E; // opcode for medium removal + scsiCmdBuf[4] = TUint8(aFlag); // prevent(1)/allow(0) medium removal + } + +void BuildTestUnitReady() + // + // Builds test unit ready command + // + { + // Zero out the buf + scsiCmdBuf.FillZ(SCSI_UNIT_READY_LEN); + scsiCmdBuf[0] = 0; // opcode for test unit ready + + scsiCmdBuf.SetLength(SCSI_UNIT_READY_LEN); + } + +void BuildStartStopUnit(TInt aFlag) + // + // Builds start/stop unit command + // + { + const TUint8 KStartMask = 0x01; + const TUint8 KLoejMask = 0x02; + // Zero out the buf + scsiCmdBuf.FillZ(SCSI_START_STOP_LEN); + scsiCmdBuf[0] = 0x1B; // opcode for test unit ready + scsiCmdBuf[1] = 0x01; // set immed bit to true + scsiCmdBuf[4] = TUint8((aFlag == 1) ? KLoejMask & KStartMask : KLoejMask); // LOEJ + START or STOP + + scsiCmdBuf.SetLength(SCSI_START_STOP_LEN); + } + +void fillInt(TUint8* dest, TInt source) + // + // Copy an int. Little endian + // + { + for (TInt i = 0; i < 4; i++) + { + *dest++ = TUint8((source >> i*8) & 0xFF); + } + } + +TInt extractInt(const TUint8* aBuf) + // + // Extract an integer from a buffer. Assume little endian + // + { + return aBuf[0] + (aBuf[1] << 8) + (aBuf[2] << 16) + (aBuf[3] << 24); + } + +void createCBW(TDes8& aCbw, TInt aDCBWTag, TInt aDataTransferLen, TUint8 aInOutFlag, TDes8& aCBWCB, TUint8 aTestLun) + // + // aCbw: stores CBW + // aDCBWTag: a command block tag sent by the host. Used to associates a CSW + // with corresponding CBW + // aDataTranferLen: the number of bytes the host expects to transfer + // aInOutFlag: value for bmCBWFlags field, indicating the direction of transfer + // aCBWCB the actual command to be wrapped + // aTestLun local unit number + { + // Zero out aCbw + aCbw.SetLength(KCbwLength); + aCbw.FillZ(); + + // dCBWSignature field, the value comes from spec + TInt dCBWSignature = 0x43425355; + fillInt(&aCbw[0], dCBWSignature); + // dCBWTag field + fillInt(&aCbw[4], aDCBWTag); + // dCBWDataTransferLength field + fillInt(&aCbw[8], aDataTransferLen); + // bmCBWFlags field + aCbw[12] = aInOutFlag; + aCbw[13] = aTestLun; + // bCBWCBLength field + aCbw[14] = TUint8(aCBWCB.Length()); + + // CBWCB field + for (TInt i = 0; i < aCbw[14]; ++i) + { + aCbw[15 + i] = aCBWCB[i]; + } + } +