os/kernelhwsrv/kerneltest/f32test/shostmassstorage/testclient/usbtestmsclient/protocol/cscsiserverprotocol.cpp
Update contrib.
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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
18 #include <e32property.h>
22 #include "usbmsshared.h"
24 #include "drivemanager.h"
25 #include "drivepublisher.h"
26 #include "tscsiserverreq.h"
27 #include "tscsiservercmds.h"
28 #include "mserverprotocol.h"
29 #include "mdevicetransport.h"
32 #include "cscsiserverprotocol.h"
37 TMediaWriteMan::TMediaWriteMan()
40 iMediaWriteSize(KDefaultMediaWriteSize)
44 void TMediaWriteMan::ReportHighSpeedDevice()
47 iMediaWriteSize = KHsMediaWriteSize;
48 __PRINT1(_L("HS Device reported: SCSI will use %d bytes disk write size"), iMediaWriteSize);
52 TInt64 TMediaWriteMan::Start(TUint32 aLba, TUint32 aLength, TUint32 aBlockSize)
55 iOffset = static_cast<TInt64>(aLba) * aBlockSize;
56 iBytesRemain = aLength * aBlockSize;
58 TInt64 theEnd = iOffset + iBytesRemain;
62 TUint32 TMediaWriteMan::NextPacket()
65 return (iBytesRemain < iMediaWriteSize) ? iBytesRemain : iMediaWriteSize;
69 void TMediaWriteMan::Reset()
75 void TMediaWriteMan::SetOffset(const TInt64& aOffset, TUint aLength)
77 iOffset = aOffset + aLength;
78 iBytesRemain -= aLength;
81 TUint32 TMediaWriteMan::GetPacketLength() const
83 // KMaxBufSize or the MediaWriteSize, whichever is smallest.
84 TUint32 thisLength = (iBytesRemain > KMaxBufSize) ? KMaxBufSize : iBytesRemain;
85 thisLength = (thisLength > iMediaWriteSize) ? iMediaWriteSize : thisLength;
91 Creates the CScsiProtocol object. Called during controller initialisation.
93 @param aDriveManager reference to the drive manager object
95 CScsiServerProtocol* CScsiServerProtocol::NewL(CDriveManager& aDriveManager)
98 CScsiServerProtocol* self = new (ELeave) CScsiServerProtocol(aDriveManager);
99 CleanupStack::PushL(self);
106 CScsiServerProtocol* CScsiServerProtocol::NewL(CDriveManager& aDriveManager, TTestParser* aTestParser)
109 CScsiServerProtocol* self = new (ELeave) CScsiServerProtocol(aDriveManager, aTestParser);
110 CleanupStack::PushL(self);
121 @param aDriveManager reference to the drive manager object
123 CScsiServerProtocol::CScsiServerProtocol(CDriveManager& aDriveManager)
124 : iDriveManager(aDriveManager)
128 iWriteTransferPublisher = CUsbWriteTransferPublisher::NewL(iBytesWritten);
129 iReadTransferPublisher = CUsbReadTransferPublisher::NewL(iBytesRead);
131 for (TUint i = 0; i < KUsbMsMaxDrives; i++)
134 iBytesWritten[i] = 0;
139 CScsiServerProtocol::CScsiServerProtocol(CDriveManager& aDriveManager, TTestParser* aTestParser)
140 : iDriveManager(aDriveManager),
141 iTestParser(aTestParser)
145 iWriteTransferPublisher = CUsbWriteTransferPublisher::NewL(iBytesWritten);
146 iReadTransferPublisher = CUsbReadTransferPublisher::NewL(iBytesRead);
148 for (TUint i = 0; i < KUsbMsMaxDrives; i++)
151 iBytesWritten[i] = 0;
157 CScsiServerProtocol::~CScsiServerProtocol()
161 delete iWriteTransferPublisher;
162 delete iReadTransferPublisher;
166 void CScsiServerProtocol::ConstructL()
173 Associates the transport with the protocol. Called during initialisation of the controller.
175 @param aTransport pointer to the transport object
177 void CScsiServerProtocol::RegisterTransport(MDeviceTransport* aTransport)
180 iTransport = aTransport;
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.
189 This function is preferably called before actual MS data transfer operation
190 starts, and usually only once.
193 void CScsiServerProtocol::ReportHighSpeedDevice()
196 iMediaWriteMan.ReportHighSpeedDevice();
200 void CScsiServerProtocol::SetParameters(const TMassStorageConfig& aConfig)
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.
213 @return ETrue if command was decoded and executed successfully
215 TBool CScsiServerProtocol::DecodePacket(TPtrC8& aData, TUint8 aLun)
218 TScsiServerReq* cdb = NULL;
219 TRAPD(err, cdb = cdb->CreateL(static_cast<TScsiServerReq::TOperationCode>(aData[0]), aData));
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);
229 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb);
232 TScsiServerReq::TOperationCode operationCode = cdb->iOperationCode;
233 if (aLun > iDriveManager.MaxLun())
235 __PRINT(_L("No drive available\n"));
236 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::ELuNotSupported);
241 if (operationCode != TScsiServerReq::ERequestSense)
243 iSenseInfo.SetSense(TSenseInfo::ENoSense);
246 switch (operationCode)
248 case TScsiServerReq::ETestUnitReady:
252 case TScsiServerReq::ERequestSense:
253 HandleRequestSense(*cdb);
256 case TScsiServerReq::EInquiry:
260 case TScsiServerReq::EModeSense6:
261 HandleModeSense6(*cdb);
264 case TScsiServerReq::EStartStopUnit:
265 HandleStartStopUnit(*cdb);
268 case TScsiServerReq::EPreventMediaRemoval:
269 HandlePreventMediaRemoval(*cdb);
272 case TScsiServerReq::EReadCapacity10:
273 HandleReadCapacity10(*cdb);
276 case TScsiServerReq::ERead10:
280 case TScsiServerReq::EWrite10:
284 case TScsiServerReq::EReadFormatCapacities:
285 HandleReadFormatCapacities(*cdb);
289 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidCmdCode);
293 __PRINT1(_L("DecodePacket result = %d"), iSenseInfo.SenseOk());
294 decodeGood = iSenseInfo.SenseOk();
303 Checks if drive ready
305 @param aLun Logic unit number
306 @return pointer to drive correspondent to LUN if drive mounted and ready, NULL otherwise
308 CMassStorageDrive* CScsiServerProtocol::GetCheckDrive()
312 if (iTestParser && iTestParser->SenseError() != TTestParser::ETestSenseErrorNoSense)
314 switch (iTestParser->SenseError())
316 case TTestParser::ETestSenseErrorMediaNotPresent:
317 __TESTMODEPRINT("Set SENSE ERROR(ENotReady, EMediaNotPresent)");
318 iSenseInfo.SetSense(TSenseInfo::ENotReady,
319 TSenseInfo::EMediaNotPresent);
323 case TTestParser::ETestSenseErrorUnitAttention:
325 __TESTMODEPRINT("Set SENSE ERROR(EUnitAttention, ENotReadyToReadyChange)");
326 iSenseInfo.SetSense(TSenseInfo::EUnitAttention,
327 TSenseInfo::ENotReadyToReadyChange);
330 iTestParser->ClrSenseError();
335 CMassStorageDrive* drive = iDriveManager.Drive(iLun);
336 CMassStorageDrive::TMountState mountState = drive->MountState();
338 if (mountState == CMassStorageDrive::EDisconnected || mountState == CMassStorageDrive::EConnecting)
340 __PRINT(_L("Drive disconnected\n"));
341 iSenseInfo.SetSense(TSenseInfo::ENotReady,
342 TSenseInfo::EMediaNotPresent);
346 TLocalDriveRef::TDriveState state = drive->CheckDriveState();
347 if (state == TLocalDriveRef::EMediaNotPresent || state == TLocalDriveRef::ELocked)
349 __PRINT1(_L("Media not present or locked. (state =0x%X)\n"),state);
350 iSenseInfo.SetSense(TSenseInfo::ENotReady, TSenseInfo::EMediaNotPresent);
354 if (drive->IsMediaChanged(ETrue)) //reset "media changed" status
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
363 if (mountState == CMassStorageDrive::EDisconnecting)
365 __PRINT(_L("Drive disconnecting\n"));
366 iSenseInfo.SetSense(TSenseInfo::ENotReady,
367 TSenseInfo::EMediaNotPresent);
376 Command Parser for the UNIT READY command (0x00)
378 @param aLun Logic unit number
379 @return ETrue if successful,
381 TBool CScsiServerProtocol::HandleUnitReady()
384 return GetCheckDrive() ? ETrue : EFalse;
389 Command Parser for the REQUEST SENSE command (0x03)
391 @return ETrue if successful,
393 TBool CScsiServerProtocol::HandleRequestSense(const TScsiServerReq& aRequest)
396 const TScsiServerRequestSenseReq request = static_cast<const TScsiServerRequestSenseReq&>(aRequest);
397 __PRINT1(_L("length = %d\n"), request.iAllocationLength);
399 TScsiServerRequestSenseResp requestSense;
400 requestSense.iAllocationLength = request.iAllocationLength;
402 requestSense.SetResponseCode(TScsiServerRequestSenseResp::ECurrentErrors);
403 requestSense.iSensePtr = &iSenseInfo;
404 requestSense.Encode(iCommandBuf);
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]);
409 TPtrC8 writeBuf = iCommandBuf.Left(request.iAllocationLength);
410 iTransport->SetupDataIn(writeBuf);
412 // clear the sense info
413 iSenseInfo.SetSense(TSenseInfo::ENoSense);
419 Command Parser for the INQUIRY command (0x12)
421 @param aLun Logic unit number
422 @return ETrue if successful,
424 TBool CScsiServerProtocol::HandleInquiry(const TScsiServerReq& aRequest)
427 const TScsiServerInquiryReq request = static_cast<const TScsiServerInquiryReq&>(aRequest);
429 if (request.iCmdDt || request.iEvpd || request.iPage || iLun >= KUsbMsMaxDrives)
431 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb);
435 TScsiServerInquiryResp inquiry(iConfig);
437 inquiry.SetAllocationLength(request.iAllocationLength);
440 if (iTestParser && !iTestParser->Removable())
442 __TESTMODEPRINT("RMB Cleared");
443 inquiry.SetNotRemovable();
447 inquiry.Encode(iCommandBuf);
449 TUint length = inquiry.Length();
451 TPtrC8 writeBuf = iCommandBuf.Left(length);
452 iTransport->SetupDataIn(writeBuf);
454 iSenseInfo.SetSense(TSenseInfo::ENoSense);
460 Command Parser for the START STOP UNIT command (0x1B)
462 @param aData command data (started form position 1)
463 @param aLun Logic unit number
464 @return ETrue if successful, TFalse otherwise
466 TBool CScsiServerProtocol::HandleStartStopUnit(const TScsiServerReq& aRequest)
470 const TScsiServerStartStopUnitReq request = static_cast<const TScsiServerStartStopUnitReq&>(aRequest);
474 if(request.iStart) //Start unit
476 iDriveManager.Connect(iLun);
477 __PRINT(_L("Load media\n"));
480 iBytesRead[iLun] = 0;
481 iBytesWritten[iLun] = 0;
483 // publish the initial values
484 iWriteTransferPublisher->DoPublishDataTransferredEvent();
485 iReadTransferPublisher->DoPublishDataTransferredEvent();
489 iDriveManager.SetCritical(iLun, EFalse);
490 iDriveManager.Disconnect(iLun);
491 __PRINT(_L("Unload media\n"));
500 CMassStorageDrive* drive = iDriveManager.Drive(iLun);
502 TInt timeLeft (20); // 1 sec timeout
503 CMassStorageDrive::TMountState mountState;
507 User::After(1000 * 50); // 50 mSec
509 mountState = drive->MountState();
511 if ((!request.iStart && mountState != CMassStorageDrive::EConnected)
514 (mountState == CMassStorageDrive::EDisconnecting ||
515 mountState == CMassStorageDrive::EConnected)))
519 } while (timeLeft>0);
522 iSenseInfo.SetSense(TSenseInfo::ENotReady,
523 TSenseInfo::EAscLogicalUnitDoesNotRespondToSelection);
529 Command Parser for the PREVENT/ALLOW MEDIA REMOVAL command (0x1E)
531 @param aData command data (started form position 1)
532 @param aLun Logic unit number
533 @return ETrue if successful.
535 TBool CScsiServerProtocol::HandlePreventMediaRemoval(const TScsiServerReq& aRequest)
538 const TScsiServerPreventMediaRemovalReq& request = static_cast<const TScsiServerPreventMediaRemovalReq&>(aRequest);
539 __FNLOG("CScsiProtocol::HandlePreventMediaRemoval");
540 CMassStorageDrive* drive = GetCheckDrive();
546 iDriveManager.SetCritical(iLun, request.iPrevent);
551 /** Cancel active state, Invoked by transnport when it stops */
552 TInt CScsiServerProtocol::Cancel()
555 iDriveManager.SetCritical(CDriveManager::KAllLuns, EFalse);
560 TBool CScsiServerProtocol::HandleReadFormatCapacities(const TScsiServerReq& aRequest)
562 * Command Parser for the READ FORMAT CAPACITIES command (0x23)
564 * @return ETrue if successful, else a standard Symbian OS error code.
568 const TScsiServerReadFormatCapacitiesReq& request = static_cast<const TScsiServerReadFormatCapacitiesReq&>(aRequest);
570 CMassStorageDrive* drive = NULL;
571 for (TInt i = 0; i < 10; i++)
573 drive = GetCheckDrive();
586 TUint32 numBlocks = I64LOW(drive->MediaParams().NumBlocks());
588 TScsiServerReadFormatCapacitiesResp response(request.AllocationLength());
589 response.SetNumberBlocks(numBlocks);
591 response.Encode(iCommandBuf);
592 TPtrC8 writeBuf = iCommandBuf;
593 iTransport->SetupDataIn(writeBuf);
599 Command Parser for the READ CAPACITY(10) command (0x25)
601 @param aData command data (started form position 1)
602 @param aLun Logic unit number
603 @return ETrue if successful.
605 TBool CScsiServerProtocol::HandleReadCapacity10(const TScsiServerReq& aRequest)
608 const TScsiServerReadCapacity10Req& request = static_cast<const TScsiServerReadCapacity10Req&>(aRequest);
609 CMassStorageDrive* drive = GetCheckDrive();
615 if (request.iPmi || request.iLogicalBlockAddress) //do not support partial medium indicator
617 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb);
621 TScsiServerReadCapacity10Resp response;
622 response.Set(drive->MediaParams().BlockSize(), drive->MediaParams().NumBlocks());
623 response.Encode(iCommandBuf);
625 TPtrC8 writeBuf = iCommandBuf;
626 iTransport->SetupDataIn(writeBuf);
633 Command Parser for the READ10 command (0x28)
635 @param aData command data (started form position 1)
636 @param aLun Logic unit number
637 @return ETrue if successful.
639 TBool CScsiServerProtocol::HandleRead10(const TScsiServerReq& aRequest)
642 const TScsiServerRead10Req& request = static_cast<const TScsiServerRead10Req&>(aRequest);
643 CMassStorageDrive* drive = GetCheckDrive();
649 if (request.iProtect)
651 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb);
655 if (!request.iTransferLength)
657 return ETrue; // do nothing - this is not an error
660 TUint32 blockSize = drive->MediaParams().BlockSize();
662 const TInt64 bOffset = static_cast<TInt64>(request.iLogicalBlockAddress) * blockSize;
663 const TInt bLength = request.iTransferLength * blockSize;
664 const TInt64 theEnd = bOffset + bLength;
666 if (theEnd > drive->MediaParams().Size()) //check if media big enough for this request
668 __PRINT(_L("err - Request ends out of media\n"));
669 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::ELbaOutOfRange);
673 // check if our buffer can hold requested data
674 if (iDataBuf.MaxLength() < bLength)
676 TRAPD(err,iDataBuf.ReAllocL(bLength));
679 __PRINT(_L("err - Buffer too small\n"));
680 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb);
685 iDataBuf.SetLength(bLength);
686 TInt err = drive->Read(bOffset, bLength, iDataBuf);
689 __PRINT1(_L("Read failed, err=%d\n"), err);
690 iSenseInfo.SetSense(TSenseInfo::ENotReady, TSenseInfo::EMediaNotPresent);
694 TPtrC8 writeBuf = iDataBuf;
697 iBytesRead[iLun] += writeBuf.Length();
698 iReadTransferPublisher->StartTimer();
700 // Set up data write to the host
704 TBool test = iTestParser->DInSearch(writeBuf);
707 iTransport->SetupDataIn(writeBuf);
713 Command Parser for the WRITE(10) command (0x2A)
715 @param aData command data (started form position 1)
716 @param aLun Logic unit number
717 @return ETrue if successful.
719 TBool CScsiServerProtocol::HandleWrite10(const TScsiServerReq& aRequest)
722 const TScsiServerWrite10Req& request = static_cast<const TScsiServerWrite10Req&>(aRequest);
723 CMassStorageDrive* drive = GetCheckDrive();
728 if (request.iProtect)
730 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb);
734 if (!request.iTransferLength)
736 return ETrue; // do nothing - this is not an error
739 const TMediaParams& params = drive->MediaParams();
741 if (params.IsWriteProtected() ||
744 iSenseInfo.SetSense(TSenseInfo::EDataProtection, TSenseInfo::EWriteProtected);
748 TInt64 theEnd = iMediaWriteMan.Start(request.iLogicalBlockAddress, request.iTransferLength, params.BlockSize());
749 if (theEnd > params.Size()) //check if media big enough for this request
751 __PRINT(_L("err - Request ends out of media\n"));
752 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::ELbaOutOfRange);
756 TUint32 thisLength = iMediaWriteMan.GetPacketLength();
758 // check if our buffer can hold requested data
759 if (iDataBuf.MaxLength() < thisLength)
761 TRAPD(err,iDataBuf.ReAllocL(thisLength));
764 __PRINT(_L("err - Buffer too small\n"));
765 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb);
770 iDataBuf.SetLength(thisLength);
771 TPtr8 readBuf = iDataBuf.LeftTPtr(iDataBuf.Length());
774 iBytesWritten[iLun] += readBuf.Length();
775 iWriteTransferPublisher->StartTimer();
776 iTransport->SetupDataOut(readBuf);
781 void CScsiServerProtocol::MediaWriteAbort()
784 iMediaWriteMan.Reset();
785 iSenseInfo.SetSense(TSenseInfo::EAbortedCommand);
789 Called by the transport when the requested data has been read or an error has
790 occurred during the read.
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.
799 TInt CScsiServerProtocol::MediaWritePacket(TUint& aBytesWritten)
803 if (iMediaWriteMan.Active() == EFalse)
805 iSenseInfo.SetSense(TSenseInfo::EAbortedCommand);
809 CMassStorageDrive* drive = GetCheckDrive();
816 if (iTestParser && iTestParser->Enabled())
818 TInt testCase = iTestParser->TestCase();
819 if (testCase == TTestParser::ETestCaseDoStallData)
821 iTestParser->DecTestCounter();
823 TInt testCounter = iTestParser->TestCounter();
824 if (testCounter == 1)
826 __TESTMODEPRINT1("Aborting MediaWritePacket (Data Stall) x%x", iMediaWriteMan.BytesRemain());
827 __TESTMODEPRINT2("Offset=0x%lx Length=%x",
828 iMediaWriteMan.Offset(), iDataBuf.Length());
831 else if (testCounter == 0)
833 // Display the next write and clear the test
834 iTestParser->ClrTestCase();
835 __TESTMODEPRINT2("Offset=0x%lx Length=%x",
836 iMediaWriteMan.Offset(), iDataBuf.Length());
839 else if (testCase == TTestParser::ETestCaseDoResidue)
841 iTestParser->DecTestCounter();
842 TInt testCounter = iTestParser->TestCounter();
844 if (testCounter == 1)
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());
853 else if (testCounter == 0)
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());
862 __TESTMODEPRINT3("MediaWritePacket[%x] Offset=0x%lx Length=0x%x",
863 testCounter, iMediaWriteMan.Offset(), iDataBuf.Length());
870 const TInt64 bOffset = iMediaWriteMan.Offset();
871 iMediaWriteMan.Reset();
873 __PRINT1(_L("SCSI: writing %d bytes\n"), iDataBuf.Length());
879 TBool test = iTestParser->DoutSearch(iDataBuf);
882 // Do not write test control blocks to media
886 // ********* Write data to the drive ********
887 err = drive->Write(bOffset, iDataBuf);
891 // ********* Write data to the drive ********
892 err = drive->Write(bOffset, iDataBuf);
896 __PRINT1(_L("Error after write = 0x%X \n"), err);
897 iSenseInfo.SetSense(TSenseInfo::EAbortedCommand);
901 TUint thisLength = iDataBuf.Length();
902 aBytesWritten = thisLength;
904 iMediaWriteMan.SetOffset(bOffset, thisLength);
906 if (iMediaWriteMan.BytesRemain() == 0)
908 return iSenseInfo.SenseOk() ? KErrNone : KErrAbort;
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);
917 thisLength = nextPacketLength;
920 if (bytesAvail < nextPacketLength)
922 // Not enough data is available at the transport to satisfy the
923 // request, so return KErrNotReady to indicate that the transport
925 thisLength = nextPacketLength;
930 thisLength = (thisLength > KMaxBufSize) ? KMaxBufSize : thisLength;
932 iDataBuf.SetLength(thisLength);
933 TPtr8 readBuf = iDataBuf.LeftTPtr(iDataBuf.Length());
934 iTransport->SetupDataOut(readBuf);
935 return wait ? KErrNotReady : KErrCompletion;
940 Command Parser for the MODE SENSE(06) command (0x1A)
942 @return ETrue if successful.
944 TBool CScsiServerProtocol::HandleModeSense6(const TScsiServerReq& aRequest)
947 const TScsiServerModeSense6Req& request = static_cast<const TScsiServerModeSense6Req&>(aRequest);
949 TScsiServerModeSense6Resp response;
950 response.SetAllocationLength(request.iAllocationLength);
952 if (request.iPageCode != TScsiServerModeSense6Req::KAllPages ||
953 request.iPageControl == TScsiServerModeSense6Req::EChangeableValues)
955 __PRINT(_L("TSenseInfo::EIllegalRequest,TSenseInfo::EInvalidFieldInCdb"));
956 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest,TSenseInfo::EInvalidFieldInCdb);
959 if (request.iPageControl != TScsiServerModeSense6Req::EDefaultValues)
961 //check if drive write protected
962 CMassStorageDrive* drive = GetCheckDrive();
965 __PRINT(_L("drive == null"));
972 response.SetWp(iTestParser->WriteProtect());
975 response.SetWp(drive->MediaParams().IsWriteProtected());
979 response.Encode(iCommandBuf);
981 TPtrC8 writeBuf = iCommandBuf;
982 iTransport->SetupDataIn(writeBuf);
983 return iSenseInfo.SenseOk();