51 @param aStatusPollingInterval The polling interval |
54 @param aStatusPollingInterval The polling interval |
52 @return CScsiProtocol* A reference to the |
55 @return CScsiProtocol* A reference to the |
53 */ |
56 */ |
54 CScsiProtocol* CScsiProtocol::NewL(TLun aLun, MTransport& aTransport) |
57 CScsiProtocol* CScsiProtocol::NewL(TLun aLun, MTransport& aTransport) |
55 { |
58 { |
56 __MSFNSLOG |
59 CScsiProtocol* r = new (ELeave) CScsiProtocol(aTransport); |
57 CScsiProtocol* r = new (ELeave) CScsiProtocol(aTransport); |
60 |
58 |
61 CleanupStack::PushL(r); |
59 CleanupStack::PushL(r); |
62 r->ConstructL(aLun); |
60 r->ConstructL(aLun); |
63 CleanupStack::Pop(); |
61 CleanupStack::Pop(); |
64 return r; |
62 return r; |
|
63 } |
65 } |
64 |
66 |
65 void CScsiProtocol::ConstructL(TLun aLun) |
67 void CScsiProtocol::ConstructL(TLun aLun) |
66 { |
68 { |
67 __MSFNLOG |
69 // iState = EEntry; |
68 // iState = EEntry; |
|
69 iFsm = CMassStorageFsm::NewL(*this); |
70 iFsm = CMassStorageFsm::NewL(*this); |
70 |
71 |
71 const TInt blockLength = 0x200; |
72 const TInt blockLength = 0x200; |
72 |
73 |
73 iHeadbuf.CreateL(blockLength); |
74 iHeadbuf.CreateL(blockLength); |
77 |
78 |
78 CScsiProtocol::CScsiProtocol(MTransport& aTransport) |
79 CScsiProtocol::CScsiProtocol(MTransport& aTransport) |
79 : iSpcInterface(aTransport), |
80 : iSpcInterface(aTransport), |
80 iSbcInterface(NULL) |
81 iSbcInterface(NULL) |
81 { |
82 { |
82 __MSFNLOG |
|
83 } |
83 } |
84 |
84 |
85 |
85 |
86 CScsiProtocol::~CScsiProtocol() |
86 CScsiProtocol::~CScsiProtocol() |
87 { |
87 { |
88 __MSFNLOG |
|
89 delete iFsm; |
88 delete iFsm; |
90 iHeadbuf.Close(); |
89 iHeadbuf.Close(); |
91 iTailbuf.Close(); |
90 iTailbuf.Close(); |
92 delete iSbcInterface; |
91 delete iSbcInterface; |
93 } |
92 } |
94 |
93 |
95 |
94 |
96 void CScsiProtocol::InitialiseUnitL() |
95 void CScsiProtocol::InitialiseUnitL() |
97 { |
96 { |
98 __MSFNLOG |
|
99 iState = EDisconnected; |
97 iState = EDisconnected; |
100 |
98 |
101 // A device may take time to mount the media. If the device fails attempt to |
99 // A device may take time to mount the media. If the device fails attempt to |
102 // retry the connection for a number of seconds |
100 // retry the connection for a number of seconds |
103 TInt retryCounter = 20; |
101 TInt retryCounter = 20; |
104 do |
102 do |
105 { |
103 { |
106 retryCounter--; |
104 retryCounter--; |
107 TInt err = iFsm->ConnectLogicalUnitL(); |
105 TInt err = iFsm->ConnectLogicalUnitL(); |
115 break; |
113 break; |
116 } |
114 } |
117 User::After(1000 * 200); // 200 mS |
115 User::After(1000 * 200); // 200 mS |
118 } |
116 } |
119 while (retryCounter); |
117 while (retryCounter); |
120 } |
118 } |
121 |
119 |
122 |
120 |
123 void CScsiProtocol::UninitialiseUnitL() |
121 void CScsiProtocol::UninitialiseUnitL() |
124 { |
122 { |
125 __MSFNLOG |
|
126 iFsm->DisconnectLogicalUnitL(); |
123 iFsm->DisconnectLogicalUnitL(); |
127 } |
124 } |
128 |
125 |
129 TBool CScsiProtocol::IsConnected() |
126 TBool CScsiProtocol::IsConnected() |
130 { |
127 { |
131 __MSFNLOG |
128 return (iState == EConnected)? ETrue : EFalse; |
132 return (iState == EConnected)? ETrue : EFalse; |
|
133 } |
129 } |
134 |
130 |
135 void CScsiProtocol::ReadL(TPos aPos, |
131 void CScsiProtocol::ReadL(TPos aPos, |
136 TDes8& aBuf, |
132 TDes8& aBuf, |
137 TInt aLength) |
133 TInt aLength) |
138 { |
134 { |
139 __MSFNLOG |
|
140 |
135 |
141 if (!iSbcInterface) |
136 if (!iSbcInterface) |
142 User::Leave(KErrNotSupported); |
137 User::Leave(KErrNotSupported); |
143 |
138 |
144 if(!IsConnected()) |
139 if(!IsConnected()) |
145 User::Leave(KErrNotReady); |
140 User::Leave(KErrNotReady); |
146 iSbcInterface->iBlockTransfer.ReadL(*this, aPos, aLength, aBuf); |
141 iSbcInterface->iBlockTransfer.ReadL(*this, aPos, aLength, aBuf); |
147 } |
142 } |
148 |
143 |
149 |
144 |
150 void CScsiProtocol::BlockReadL(TPos aPos, TDes8& aCopybuf, TInt aLen) |
145 void CScsiProtocol::BlockReadL(TPos aPos, TDes8& aCopybuf, TInt aLen) |
151 { |
146 { |
152 __MSFNLOG |
|
153 if (!iSbcInterface) |
147 if (!iSbcInterface) |
154 User::Leave(KErrNotSupported); |
148 User::Leave(KErrNotSupported); |
155 |
149 |
156 __ASSERT_DEBUG(aPos % iSbcInterface->iBlockTransfer.BlockLength() == 0, |
150 __ASSERT_DEBUG(aPos % iSbcInterface->iBlockTransfer.BlockLength() == 0, |
157 User::Panic(KUsbMsHostPanicCat, EBlockDevice)); |
151 User::Panic(KUsbMsHostPanicCat, EBlockDevice)); |
158 |
152 |
159 const TInt blockLen = iSbcInterface->iBlockTransfer.BlockLength(); |
153 const TInt blockLen = iSbcInterface->iBlockTransfer.BlockLength(); |
160 TInt len = aLen; |
154 TInt len = aLen; |
161 |
155 |
164 if (I64HIGH(lba)) |
158 if (I64HIGH(lba)) |
165 { |
159 { |
166 User::LeaveIfError(KErrOverflow); |
160 User::LeaveIfError(KErrOverflow); |
167 } |
161 } |
168 |
162 |
169 TInt err = iSbcInterface->Read10L(I64LOW(lba), aCopybuf, len); |
163 TInt err = iSbcInterface->Read10L(I64LOW(lba), aCopybuf, len); |
170 if (err) |
164 if (err) |
171 { |
165 { |
172 __SCSIPRINT1(_L("READ(10) Err=%d"), err); |
166 OstTrace1(TRACE_SHOSTMASSSTORAGE_SCSI, CSCSIPROTOCOL_10, |
|
167 "READ(10) Err=%d", err); |
173 User::LeaveIfError(DoCheckConditionL()); |
168 User::LeaveIfError(DoCheckConditionL()); |
174 } |
169 } |
175 |
170 |
176 // handle residue |
171 // handle residue |
177 while (len != aLen) |
172 while (len != aLen) |
178 { |
173 { |
179 __SCSIPRINT2(_L("SCSI Read Residue 0x%x bytes read (0x%x)"), len, aLen); |
174 OstTraceExt2(TRACE_SHOSTMASSSTORAGE_SCSI, CSCSIPROTOCOL_11, |
180 __SCSIPRINT2(_L("Pos=0x%lx Len=0x%x"), aPos, aLen); |
175 "SCSI Read Residue 0x%x bytes read (0x%x)", len, aLen); |
|
176 OstTraceExt2(TRACE_SHOSTMASSSTORAGE_SCSI, CSCSIPROTOCOL_12, |
|
177 "Pos=0x%lx Len=0x%x", aPos, aLen); |
181 |
178 |
182 // read next block |
179 // read next block |
183 |
180 |
184 // full blocks read in bytes |
181 // full blocks read in bytes |
185 TInt bytesRead = len/blockLen * blockLen; |
182 TInt bytesRead = len/blockLen * blockLen; |
186 aPos += bytesRead; |
183 aPos += bytesRead; |
187 aLen -= bytesRead; |
184 aLen -= bytesRead; |
188 len = aLen; |
185 len = aLen; |
189 |
186 |
190 __SCSIPRINT3(_L("New Pos=0x%lx Len=0x%x (bytes read = %x)"), |
187 OstTraceExt3(TRACE_SHOSTMASSSTORAGE_SCSI, CSCSIPROTOCOL_13, |
191 aPos, aLen, bytesRead); |
188 "New Pos=0x%lx Len=0x%x (bytes read = %x)", aPos, aLen, bytesRead); |
192 |
189 |
193 aCopybuf.SetLength(bytesRead); |
190 aCopybuf.SetLength(bytesRead); |
194 |
191 |
195 // read rest of the block |
192 // read rest of the block |
196 TInt err = iSbcInterface->Read10L(aPos/blockLen, aCopybuf, len); |
193 TInt err = iSbcInterface->Read10L(aPos/blockLen, aCopybuf, len); |
204 |
201 |
205 void CScsiProtocol::WriteL(TPos aPosition, |
202 void CScsiProtocol::WriteL(TPos aPosition, |
206 TDesC8& aBuf, |
203 TDesC8& aBuf, |
207 TInt aLength) |
204 TInt aLength) |
208 { |
205 { |
209 __MSFNLOG |
|
210 if (!iSbcInterface) |
206 if (!iSbcInterface) |
211 User::Leave(KErrNotSupported); |
207 User::Leave(KErrNotSupported); |
212 |
208 |
213 if(!IsConnected()) |
209 if(!IsConnected()) |
214 User::Leave(KErrNotReady); |
210 User::Leave(KErrNotReady); |
215 iSbcInterface->iBlockTransfer.WriteL(*this, aPosition, aLength, aBuf); |
211 iSbcInterface->iBlockTransfer.WriteL(*this, aPosition, aLength, aBuf); |
216 } |
212 } |
217 |
213 |
218 |
214 |
219 void CScsiProtocol::BlockWriteL(TPos aPos, TDesC8& aCopybuf, TUint aOffset, TInt aLen) |
215 void CScsiProtocol::BlockWriteL(TPos aPos, TDesC8& aCopybuf, TUint aOffset, TInt aLen) |
220 { |
216 { |
221 __MSFNLOG |
|
222 if (!iSbcInterface) |
217 if (!iSbcInterface) |
223 User::Leave(KErrNotSupported); |
218 User::Leave(KErrNotSupported); |
224 |
219 |
225 __ASSERT_DEBUG(aPos % iSbcInterface->iBlockTransfer.BlockLength() == 0, |
220 __ASSERT_DEBUG(aPos % iSbcInterface->iBlockTransfer.BlockLength() == 0, |
226 User::Panic(KUsbMsHostPanicCat, EBlockDevice)); |
221 User::Panic(KUsbMsHostPanicCat, EBlockDevice)); |
227 const TInt blockLen = iSbcInterface->iBlockTransfer.BlockLength(); |
222 const TInt blockLen = iSbcInterface->iBlockTransfer.BlockLength(); |
228 TInt len = aLen; |
223 TInt len = aLen; |
229 TInt err = iSbcInterface->Write10L(aPos/blockLen, aCopybuf, aOffset, len); |
224 TInt err = iSbcInterface->Write10L(aPos/blockLen, aCopybuf, aOffset, len); |
230 if (err) |
225 if (err) |
231 { |
226 { |
232 User::LeaveIfError(DoCheckConditionL()); |
227 User::LeaveIfError(DoCheckConditionL()); |
233 } |
228 } |
234 |
229 |
235 while (len != aLen) |
230 while (len != aLen) |
236 { |
231 { |
237 // handle residue |
232 // handle residue |
238 __SCSIPRINT2(_L("SCSI Write Residue 0x%x bytes read (0x%x)"), len, aLen); |
233 OstTraceExt2(TRACE_SHOSTMASSSTORAGE_SCSI, CSCSIPROTOCOL_20, |
239 __SCSIPRINT2(_L("Pos=0x%lx Len=0x%x"), aPos, aLen); |
234 "SCSI Write Residue 0x%x bytes read (0x%x)", len, aLen); |
|
235 OstTraceExt2(TRACE_SHOSTMASSSTORAGE_SCSI, CSCSIPROTOCOL_21, |
|
236 "Pos=0x%lx Len=0x%x", aPos, aLen); |
240 |
237 |
241 // write next block |
238 // write next block |
242 |
239 |
243 // full blocks written in bytes |
240 // full blocks written in bytes |
244 TInt bytesWritten = len/blockLen * blockLen; |
241 TInt bytesWritten = len/blockLen * blockLen; |
245 aPos += bytesWritten; |
242 aPos += bytesWritten; |
246 aLen -= bytesWritten; |
243 aLen -= bytesWritten; |
247 len = aLen; |
244 len = aLen; |
248 __SCSIPRINT2(_L("New Pos=0x%lx Len=0x%x"), aPos, aLen); |
245 OstTraceExt2(TRACE_SHOSTMASSSTORAGE_SCSI, CSCSIPROTOCOL_22, |
|
246 "New Pos=0x%lx Len=0x%x", aPos, aLen); |
249 |
247 |
250 TPtrC8 buf = aCopybuf.Mid(bytesWritten); |
248 TPtrC8 buf = aCopybuf.Mid(bytesWritten); |
251 |
249 |
252 // write rest of the block |
250 // write rest of the block |
253 TInt err = iSbcInterface->Write10L(aPos/blockLen, buf, aOffset, len); |
251 TInt err = iSbcInterface->Write10L(aPos/blockLen, buf, aOffset, len); |
320 // ignore error if unsupported |
317 // ignore error if unsupported |
321 if (err != KErrUnknown) |
318 if (err != KErrUnknown) |
322 { |
319 { |
323 User::LeaveIfError(err); |
320 User::LeaveIfError(err); |
324 } |
321 } |
325 } |
322 } |
326 } |
323 } |
327 |
324 |
328 aCapsInfo.iNumberOfBlocks = lastLba + 1; |
325 aCapsInfo.iNumberOfBlocks = lastLba + 1; |
329 aCapsInfo.iBlockLength = blockLength; |
326 aCapsInfo.iBlockLength = blockLength; |
330 aCapsInfo.iWriteProtect = iWriteProtect; |
327 aCapsInfo.iWriteProtect = iWriteProtect; |
331 |
328 |
332 __SCSIPRINT3(_L("numBlock = x%x , blockLength = %x wp = %d"), |
329 OstTraceExt3(TRACE_SHOSTMASSSTORAGE_SCSI, CSCSIPROTOCOL_30, |
333 lastLba + 1, blockLength, iWriteProtect); |
330 "numBlock=x%x blockLength=x%x wp=%d", |
|
331 (TUint32)(lastLba + 1), blockLength, (TInt32)iWriteProtect); |
334 } |
332 } |
335 |
333 |
336 |
334 |
337 /** |
335 /** |
338 Perform SCSI INQUIRY command. The function leaves if the device response is not |
336 Perform SCSI INQUIRY command. The function leaves if the device response is not |
365 // KErrCommandFailed |
362 // KErrCommandFailed |
366 return err; |
363 return err; |
367 } |
364 } |
368 |
365 |
369 // print reponse |
366 // print reponse |
370 __TESTREPORT1(_L("RMB = %d"), info.iRemovable); |
367 OstTrace1(TRACE_SHOSTMASSSTORAGE_DEVICEREPORT, CSCSIPROTOCOL_40, |
371 __TESTREPORT2(_L("PERIPHERAL DEVICE TYPE = %d PQ = %d"), |
368 "RMB = %d", info.iRemovable); |
372 info.iPeripheralDeviceType, |
369 OstTraceExt2(TRACE_SHOSTMASSSTORAGE_DEVICEREPORT, CSCSIPROTOCOL_41, |
373 info.iPeripheralQualifier); |
370 "PERIPHERAL DEVICE TYPE = %d PQ = %d", |
374 __TESTREPORT1(_L("VERSION = %d"), info.iVersion); |
371 info.iPeripheralDeviceType, |
375 __TESTREPORT1(_L("RESPONSE DATA FORMAT = %d"), info.iResponseDataFormat); |
372 info.iPeripheralQualifier); |
376 __TESTREPORT3(_L("VENDOR ID %S PRODUCT ID %S REV %S"), |
373 OstTrace1(TRACE_SHOSTMASSSTORAGE_DEVICEREPORT, CSCSIPROTOCOL_42, |
377 &info.iIdentification.iVendorId, |
374 "VERSION = %d", info.iVersion); |
378 &info.iIdentification.iProductId, |
375 OstTrace1(TRACE_SHOSTMASSSTORAGE_DEVICEREPORT, CSCSIPROTOCOL_43, |
379 &info.iIdentification.iProductRev); |
376 "RESPONSE DATA FORMAT = %d", |
|
377 info.iResponseDataFormat); |
|
378 |
|
379 OstTraceData(TRACE_SHOSTMASSSTORAGE_DEVICEREPORT, CSCSIPROTOCOL_440, |
|
380 "VENDOR ID %s", |
|
381 info.iIdentification.iVendorId.Ptr(), info.iIdentification.iVendorId.Size() * 2); |
|
382 OstTraceData(TRACE_SHOSTMASSSTORAGE_DEVICEREPORT, CSCSIPROTOCOL_441, |
|
383 "PRODUCT ID %s", |
|
384 info.iIdentification.iProductId.Ptr(), info.iIdentification.iProductId.Size() * 2); |
|
385 OstTraceData(TRACE_SHOSTMASSSTORAGE_DEVICEREPORT, CSCSIPROTOCOL_442, |
|
386 "REV %s", |
|
387 info.iIdentification.iProductRev.Ptr(), info.iIdentification.iProductRev.Size() * 2); |
380 |
388 |
381 if (info.iPeripheralQualifier != 0 && info.iPeripheralQualifier != 1) |
389 if (info.iPeripheralQualifier != 0 && info.iPeripheralQualifier != 1) |
382 { |
390 { |
383 __HOSTPRINT(_L("Peripheral Qualifier[Unknown device type]")) |
391 OstTrace0(TRACE_SHOSTMASSSTORAGE_HOST, CSCSIPROTOCOL_45, |
|
392 "Peripheral Qualifier[Unknown device type]"); |
384 err = KErrUnknown; |
393 err = KErrUnknown; |
385 } |
394 } |
386 else if (info.iPeripheralDeviceType == 0) |
395 else if (info.iPeripheralDeviceType == 0) |
387 { |
396 { |
388 // SCSI SBC Direct access device |
397 // SCSI SBC Direct access device |
389 iRemovableMedia = info.iRemovable; |
398 iRemovableMedia = info.iRemovable; |
390 |
399 |
391 // SCSI Block device |
400 // SCSI Block device |
392 iSbcInterface = new (ELeave) TSbcClientInterface(iSpcInterface.Transport()); |
401 iSbcInterface = new (ELeave) TSbcClientInterface(iSpcInterface.Transport()); |
393 iSbcInterface->InitBuffers(&iHeadbuf, &iTailbuf); |
402 iSbcInterface->InitBuffers(&iHeadbuf, &iTailbuf); |
394 err = KErrNone; |
403 err = KErrNone; |
395 } |
404 } |
396 else if (info.iPeripheralDeviceType == 5) |
405 else if (info.iPeripheralDeviceType == 5) |
397 { |
406 { |
398 // SCSI MMC-2 CD-ROM device |
407 // SCSI MMC-2 CD-ROM device |
399 __HOSTPRINT(_L("Peripheral Device Type[CD-ROM]")) |
408 OstTrace0(TRACE_SHOSTMASSSTORAGE_HOST, CSCSIPROTOCOL_46, |
|
409 "Peripheral Device Type[CD-ROM]"); |
400 iRemovableMedia = info.iRemovable; |
410 iRemovableMedia = info.iRemovable; |
401 |
411 |
402 // MMC-2 is not supported. A SCSI interface call will return |
412 // MMC-2 is not supported. A SCSI interface call will return |
403 // KErrNotSupported. If SCSI support is extended in future then |
413 // KErrNotSupported. If SCSI support is extended in future then |
404 // TSbcInterface class should be replaced with a proper interface class. |
414 // TSbcInterface class should be replaced with a proper interface class. |
405 iSbcInterface = NULL; |
415 iSbcInterface = NULL; |
406 err = KErrNone; |
416 err = KErrNone; |
407 } |
417 } |
408 else |
418 else |
409 { |
419 { |
410 __HOSTPRINT(_L("Peripheral Device Type[Unsupported device type]")) |
420 OstTrace0(TRACE_SHOSTMASSSTORAGE_HOST, CSCSIPROTOCOL_47, |
411 err = KErrUnknown; |
421 "Peripheral Device Type[Unsupported device type]"); |
|
422 err = KErrUnknown; |
412 } |
423 } |
413 |
424 |
414 return err; |
425 return err; |
415 } |
426 } |
416 |
427 |
441 @return TInt KErrNone if successful, KErrCommandFailed to indicate a |
451 @return TInt KErrNone if successful, KErrCommandFailed to indicate a |
442 device status error, KErrCommandStalled to indicate a device stall |
452 device status error, KErrCommandStalled to indicate a device stall |
443 */ |
453 */ |
444 TInt CScsiProtocol::MsReadCapacityL() |
454 TInt CScsiProtocol::MsReadCapacityL() |
445 { |
455 { |
446 __MSFNLOG |
|
447 if (!iSbcInterface) |
456 if (!iSbcInterface) |
448 { |
457 { |
449 User::Leave(KErrNotSupported); |
458 User::Leave(KErrNotSupported); |
450 } |
459 } |
451 |
460 |
452 // READ CAPACITY |
461 // READ CAPACITY |
453 TUint32 blockSize; |
462 TUint32 blockSize; |
454 TUint32 lastLba; |
463 TUint32 lastLba; |
455 TInt err = iSbcInterface->ReadCapacity10L(lastLba, blockSize); |
464 TInt err = iSbcInterface->ReadCapacity10L(lastLba, blockSize); |
456 |
465 |
457 __TESTREPORT2(_L("CAPACITY: Block Size=0x%x Last LBA=0x%x"), blockSize, lastLba); |
466 OstTraceExt2(TRACE_SHOSTMASSSTORAGE_DEVICEREPORT, CSCSIPROTOCOL_50, |
|
467 "CAPACITY: Block Size=0x%x Last LBA=0x%x", blockSize, lastLba); |
458 return err; |
468 return err; |
459 } |
469 } |
460 |
470 |
461 |
471 |
462 /** |
472 /** |
531 @return TInt KErrNone if successful otherwise KErrCommandFailed to indicate a |
538 @return TInt KErrNone if successful otherwise KErrCommandFailed to indicate a |
532 device status error |
539 device status error |
533 */ |
540 */ |
534 TInt CScsiProtocol::MsPreventAllowMediaRemovalL(TBool aPrevent) |
541 TInt CScsiProtocol::MsPreventAllowMediaRemovalL(TBool aPrevent) |
535 { |
542 { |
536 __MSFNLOG |
|
537 return iSpcInterface.PreventAllowMediumRemovalL(aPrevent); |
543 return iSpcInterface.PreventAllowMediumRemovalL(aPrevent); |
538 } |
544 } |
539 |
545 |
540 |
546 |
541 TInt CScsiProtocol::DoCheckConditionL() |
547 TInt CScsiProtocol::DoCheckConditionL() |
542 { |
548 { |
543 __MSFNLOG |
|
544 User::LeaveIfError(MsRequestSenseL()); |
549 User::LeaveIfError(MsRequestSenseL()); |
545 |
550 |
546 TInt err; |
551 TInt err; |
547 |
552 |
548 // Check if init is needed |
553 // Check if init is needed |
549 if (iSenseInfo.iSenseCode == TSenseInfo::ENotReady && |
554 if (iSenseInfo.iSenseCode == TSenseInfo::ENotReady && |
550 iSenseInfo.iAdditional == TSenseInfo::EAscLogicalUnitNotReady && |
555 iSenseInfo.iAdditional == TSenseInfo::EAscLogicalUnitNotReady && |
551 iSenseInfo.iQualifier == TSenseInfo::EAscqInitializingCommandRequired) |
556 iSenseInfo.iQualifier == TSenseInfo::EAscqInitializingCommandRequired) |
552 { |
557 { |
553 if (iSbcInterface) |
558 if (iSbcInterface) |
554 { |
559 { |
555 // start unit |
560 // start unit |
556 err = iSbcInterface->StartStopUnitL(ETrue); |
561 err = iSbcInterface->StartStopUnitL(ETrue); |
557 if (err) |
562 if (err) |
558 { |
563 { |
559 User::LeaveIfError(MsRequestSenseL()); |
564 User::LeaveIfError(MsRequestSenseL()); |
560 } |
565 } |
561 } |
566 } |
562 } |
567 } |
563 |
568 |
564 err = GetSystemWideSenseError(iSenseInfo); |
569 err = GetSystemWideSenseError(iSenseInfo); |
565 |
570 |
566 TScsiState nextState = iState; |
571 TScsiState nextState = iState; |
628 KErrDisconnected could happen due to any of the following reasons: |
633 KErrDisconnected could happen due to any of the following reasons: |
629 1. The media was changed/removed - While this error is happening the file |
634 1. The media was changed/removed - While this error is happening the file |
630 extension will be notified setting the iChanged flag |
635 extension will be notified setting the iChanged flag |
631 */ |
636 */ |
632 TInt CScsiProtocol::GetSystemWideSenseError(const TSenseInfo& aSenseInfo) |
637 TInt CScsiProtocol::GetSystemWideSenseError(const TSenseInfo& aSenseInfo) |
633 { |
638 { |
634 __MSFNLOG |
639 TInt ret = KErrNone; |
635 TInt ret = KErrNone; |
640 TInt additionalError = KErrNone; |
636 TInt additionalError = KErrNone; |
641 |
637 |
642 switch(aSenseInfo.iSenseCode) |
638 switch(aSenseInfo.iSenseCode) |
643 { |
639 { |
644 case TSenseInfo::ENoSense: |
640 case TSenseInfo::ENoSense: |
645 case TSenseInfo::ERecoveredError: |
641 case TSenseInfo::ERecoveredError: |
646 ret = KErrNone; |
642 ret = KErrNone; |
647 break; |
643 break; |
648 case TSenseInfo::ENotReady: |
644 case TSenseInfo::ENotReady: |
|
645 ret = KErrNotReady; |
649 ret = KErrNotReady; |
646 additionalError = ProcessAsCodes(aSenseInfo); |
650 additionalError = ProcessAsCodes(aSenseInfo); |
647 if (additionalError != KErrNone) |
651 if (additionalError != KErrNone) |
648 { |
652 { |
649 ret = additionalError; |
653 ret = additionalError; |
650 } |
654 } |
651 break; |
655 break; |
652 case TSenseInfo::EMediumError: |
656 case TSenseInfo::EMediumError: |
653 ret = KErrCorrupt; |
657 ret = KErrCorrupt; |
654 additionalError = ProcessAsCodes(aSenseInfo); |
658 additionalError = ProcessAsCodes(aSenseInfo); |
655 if (additionalError != KErrNone) |
659 if (additionalError != KErrNone) |
656 { |
660 { |
657 ret = additionalError; |
661 ret = additionalError; |
658 } |
662 } |
659 break; |
663 break; |
660 case TSenseInfo::EUnitAttention: |
664 case TSenseInfo::EUnitAttention: |
661 ret = KErrDisconnected; |
665 ret = KErrDisconnected; |
662 break; |
666 break; |
663 case TSenseInfo::EDataProtection: |
667 case TSenseInfo::EDataProtection: |
664 ret = KErrAccessDenied; |
668 ret = KErrAccessDenied; |
665 break; |
669 break; |
666 case TSenseInfo::EIllegalRequest: |
670 case TSenseInfo::EIllegalRequest: |
667 case TSenseInfo::EHardwareError: |
671 case TSenseInfo::EHardwareError: |
668 case TSenseInfo::EBlankCheck: |
672 case TSenseInfo::EBlankCheck: |
669 case TSenseInfo::EVendorSpecific: |
673 case TSenseInfo::EVendorSpecific: |
670 case TSenseInfo::EMisCompare: |
674 case TSenseInfo::EMisCompare: |
671 ret = KErrUnknown; |
675 ret = KErrUnknown; |
672 break; |
676 break; |
673 case TSenseInfo::ECopyAborted: |
677 case TSenseInfo::ECopyAborted: |
674 case TSenseInfo::EAbortedCommand: |
678 case TSenseInfo::EAbortedCommand: |
675 ret = KErrAbort; |
679 ret = KErrAbort; |
676 break; |
680 break; |
677 case TSenseInfo::EDataOverflow: |
681 case TSenseInfo::EDataOverflow: |
678 ret = KErrOverflow; |
682 ret = KErrOverflow; |
679 break; |
683 break; |
680 default: |
684 default: |
681 ret = KErrUnknown; |
685 ret = KErrUnknown; |
682 break; |
686 break; |
683 } |
687 } |
684 |
688 |
685 return ret; |
689 return ret; |
686 } |
690 } |
687 |
691 |
688 |
692 |
689 TInt CScsiProtocol::ProcessAsCodes(const TSenseInfo& aSenseInfo) |
693 TInt CScsiProtocol::ProcessAsCodes(const TSenseInfo& aSenseInfo) |
690 { |
694 { |
691 __MSFNLOG |
695 TInt ret = KErrNone; |
692 TInt ret = KErrNone; |
696 |
693 |
697 switch(aSenseInfo.iAdditional) |
694 switch(aSenseInfo.iAdditional) |
698 { |
695 { |
|
696 case TSenseInfo::EAscLogicalUnitNotReady: |
699 case TSenseInfo::EAscLogicalUnitNotReady: |
697 case TSenseInfo::EMediaNotPresent: |
700 case TSenseInfo::EMediaNotPresent: |
698 ret = KErrNotReady; |
701 ret = KErrNotReady; |
699 break; |
702 break; |
700 |
703 |
701 case TSenseInfo::ELbaOutOfRange: |
704 case TSenseInfo::ELbaOutOfRange: |
702 ret = KErrOverflow; |
705 ret = KErrOverflow; |
703 break; |
706 break; |
704 |
707 |
705 case TSenseInfo::EWriteProtected: |
708 case TSenseInfo::EWriteProtected: |
706 ret = KErrAccessDenied; |
709 ret = KErrAccessDenied; |
707 break; |
710 break; |
708 |
711 |
709 case TSenseInfo::ENotReadyToReadyChange: |
712 case TSenseInfo::ENotReadyToReadyChange: |
710 ret = KErrNone; |
713 ret = KErrNone; |
711 break; |
714 break; |
712 |
715 |
713 case TSenseInfo::EAscLogicalUnitDoesNotRespondToSelection: |
716 case TSenseInfo::EAscLogicalUnitDoesNotRespondToSelection: |
714 case TSenseInfo::EInvalidCmdCode: |
717 case TSenseInfo::EInvalidCmdCode: |
715 case TSenseInfo::EInvalidFieldInCdb: |
718 case TSenseInfo::EInvalidFieldInCdb: |
716 case TSenseInfo::ELuNotSupported: |
719 case TSenseInfo::ELuNotSupported: |
717 case TSenseInfo::EInsufficientRes: |
720 case TSenseInfo::EInsufficientRes: |
718 ret = KErrUnknown; |
721 ret = KErrUnknown; |
719 break; |
722 break; |
720 default: |
723 default: |
721 ret = KErrNone; |
724 ret = KErrNone; |
722 break; |
725 break; |
723 } |
726 } |
724 return ret; |
727 return ret; |
725 } |
728 } |
726 |
729 |
727 |
730 |
728 /** |
731 /** |
729 Perform SCSI REQUEST SENSE command. The function leaves if the device response |
732 Perform SCSI REQUEST SENSE command. The function leaves if the device response |
730 is not compliant with the protocol standard. |
733 is not compliant with the protocol standard. |
732 @return TInt KErrNone if successful otherwise KErrCommandFailed to indicate a |
735 @return TInt KErrNone if successful otherwise KErrCommandFailed to indicate a |
733 device status error |
736 device status error |
734 */ |
737 */ |
735 TInt CScsiProtocol::MsRequestSenseL() |
738 TInt CScsiProtocol::MsRequestSenseL() |
736 { |
739 { |
737 __MSFNLOG |
|
738 return iSpcInterface.RequestSenseL(iSenseInfo) ? KErrCommandFailed : KErrNone; |
740 return iSpcInterface.RequestSenseL(iSenseInfo) ? KErrCommandFailed : KErrNone; |
739 } |
741 } |
740 |
742 |
741 |
743 |
742 void CScsiProtocol::CreateSbcInterfaceL(TUint32 aBlockLen, TUint32 aLastLba) |
744 void CScsiProtocol::CreateSbcInterfaceL(TUint32 aBlockLen, TUint32 aLastLba) |
743 { |
745 { |
744 __MSFNLOG |
|
745 // SCSI Block device |
746 // SCSI Block device |
746 ASSERT(iSbcInterface == NULL); |
747 ASSERT(iSbcInterface == NULL); |
747 iSbcInterface = new (ELeave) TSbcClientInterface(iSpcInterface.Transport()); |
748 iSbcInterface = new (ELeave) TSbcClientInterface(iSpcInterface.Transport()); |
748 iSbcInterface->InitBuffers(&iHeadbuf, &iTailbuf); |
749 iSbcInterface->InitBuffers(&iHeadbuf, &iTailbuf); |
749 iSbcInterface->SetCapacityL(aBlockLen, aLastLba); |
750 iSbcInterface->SetCapacityL(aBlockLen, aLastLba); |
750 } |
751 } |
751 |
752 |
752 |
753 |
753 void CScsiProtocol::ResetSbc() |
754 void CScsiProtocol::ResetSbc() |
754 { |
755 { |
755 __MSFNLOG |
|
756 if (iSbcInterface) |
756 if (iSbcInterface) |
757 { |
757 { |
758 delete iSbcInterface; |
758 delete iSbcInterface; |
759 iSbcInterface = NULL; |
759 iSbcInterface = NULL; |
760 } |
760 } |
761 } |
761 } |
762 |
762 |
763 |
763 |
764 void CScsiProtocol::NotifyChange(const RMessage2& aMessage) |
764 void CScsiProtocol::NotifyChange(const RMessage2& aMessage) |
765 { |
765 { |
766 __MSFNLOG |
|
767 iMediaChangeNotifier.Register(aMessage); |
766 iMediaChangeNotifier.Register(aMessage); |
768 } |
767 } |
769 |
768 |
770 |
769 |
771 void CScsiProtocol::ForceCompleteNotifyChangeL() |
770 void CScsiProtocol::ForceCompleteNotifyChangeL() |
772 { |
771 { |
773 __MSFNLOG |
|
774 iMediaChangeNotifier.DoNotifyL(); |
772 iMediaChangeNotifier.DoNotifyL(); |
775 } |
773 } |
776 |
774 |
777 |
775 |
778 void CScsiProtocol::CancelChangeNotifierL() |
776 void CScsiProtocol::CancelChangeNotifierL() |
779 { |
777 { |
780 __MSFNLOG |
|
781 iMediaChangeNotifier.DoCancelL(); |
778 iMediaChangeNotifier.DoCancelL(); |
782 } |
779 } |
783 |
780 |
784 |
781 |
785 void CScsiProtocol::SuspendL() |
782 void CScsiProtocol::SuspendL() |
786 { |
783 { |
787 __MSFNLOG |
|
788 if (iFsm->StartStopUnitRequired()) |
784 if (iFsm->StartStopUnitRequired()) |
789 { |
785 { |
790 iSbcInterface->StartStopUnitL(EFalse); |
786 iSbcInterface->StartStopUnitL(EFalse); |
791 } |
787 } |
792 } |
788 } |
793 |
789 |
794 void CScsiProtocol::ResumeL() |
790 void CScsiProtocol::ResumeL() |
795 { |
791 { |
796 __MSFNLOG |
|
797 if (iFsm->StartStopUnitRequired()) |
792 if (iFsm->StartStopUnitRequired()) |
798 { |
793 { |
799 iSbcInterface->StartStopUnitL(ETrue); |
794 iSbcInterface->StartStopUnitL(ETrue); |
800 } |
795 } |
801 } |
796 } |
802 |
797 |
803 |
798 |
804 TBool CScsiProtocol::DoScsiReadyCheckEventL() |
799 TBool CScsiProtocol::DoScsiReadyCheckEventL() |
805 { |
800 { |
806 __MSFNLOG |
801 TInt err = KErrNone; |
807 TInt err = KErrNone; |
802 |
808 |
803 if(iRemovableMedia || iState != EConnected) |
809 if(iRemovableMedia || iState != EConnected) |
804 { |
810 { |
805 iFsm->SetStatusCheck(); |
811 iFsm->SetStatusCheck(); |
806 TRAP(err, iFsm->ConnectLogicalUnitL()); |
812 TRAP(err, iFsm->ConnectLogicalUnitL()); |
807 iFsm->ClearStatusCheck(); |
813 iFsm->ClearStatusCheck(); |
808 |
814 |
809 User::LeaveIfError(err); |
815 User::LeaveIfError(err); |
810 err = iFsm->IsConnected() ? KErrNone : KErrNotReady; |
816 err = iFsm->IsConnected() ? KErrNone : KErrNotReady; |
811 } |
817 } |
812 |
818 |
813 if (iState == EConnected) |
819 if (iState == EConnected) |
814 { |
820 { |
815 if (err != KErrNone) |
821 if (err != KErrNone) |
816 { |
822 { |
817 iState = EDisconnected; |
823 iState = EDisconnected; |
818 OstTrace0(TRACE_SHOSTMASSSTORAGE_SCSI, CSCSIPROTOCOL_60, |
824 __SCSIPRINT(_L("** Disconnected Notification **")); |
819 "** Disconnected Notification **"); |
825 iMediaChangeNotifier.DoNotifyL(); |
820 iMediaChangeNotifier.DoNotifyL(); |
826 } |
821 } |
827 } |
822 } |
828 else |
823 else |
829 { |
824 { |
830 if (err == KErrNone) |
825 if (err == KErrNone) |
831 { |
826 { |
832 iState = EConnected; |
827 iState = EConnected; |
833 __SCSIPRINT(_L("** Connected Notification **")); |
828 OstTrace0(TRACE_SHOSTMASSSTORAGE_SCSI, CSCSIPROTOCOL_61, |
|
829 "** Connected Notification **"); |
834 iMediaChangeNotifier.DoNotifyL(); |
830 iMediaChangeNotifier.DoNotifyL(); |
835 } |
831 } |
836 } |
832 } |
837 return err = KErrNone ? ETrue : EFalse; |
833 return err = KErrNone ? ETrue : EFalse; |
838 } |
834 } |
839 |
835 |
840 |
836 |
841 RMediaChangeNotifier::RMediaChangeNotifier() |
837 RMediaChangeNotifier::RMediaChangeNotifier() |
842 : iRegistered(EFalse) |
838 : iRegistered(EFalse) |
843 { |
839 { |
844 __MSFNSLOG |
|
845 } |
840 } |
846 |
841 |
847 |
842 |
848 RMediaChangeNotifier::~RMediaChangeNotifier() |
843 RMediaChangeNotifier::~RMediaChangeNotifier() |
849 { |
844 { |
850 __MSFNSLOG |
|
851 if (iRegistered) |
845 if (iRegistered) |
852 iNotifier.Complete(KErrDisconnected); |
846 iNotifier.Complete(KErrDisconnected); |
853 } |
847 } |
854 |
848 |
855 /** |
849 /** |
857 |
851 |
858 @param aMessage The message to commplete the notification |
852 @param aMessage The message to commplete the notification |
859 */ |
853 */ |
860 void RMediaChangeNotifier::Register(const RMessage2& aMessage) |
854 void RMediaChangeNotifier::Register(const RMessage2& aMessage) |
861 { |
855 { |
862 __MSFNLOG |
856 iRegistered = ETrue; |
863 iRegistered = ETrue; |
857 iNotifier = aMessage; |
864 iNotifier = aMessage; |
|
865 } |
858 } |
866 |
859 |
867 |
860 |
868 void RMediaChangeNotifier::DoNotifyL() |
861 void RMediaChangeNotifier::DoNotifyL() |
869 { |
862 { |
870 __MSFNLOG |
863 CompleteNotifierL(KErrNone); |
871 CompleteNotifierL(KErrNone); |
|
872 } |
864 } |
873 |
865 |
874 void RMediaChangeNotifier::DoCancelL() |
866 void RMediaChangeNotifier::DoCancelL() |
875 { |
867 { |
876 __MSFNLOG |
868 CompleteNotifierL(KErrCancel); |
877 CompleteNotifierL(KErrCancel); |
|
878 } |
869 } |
879 |
870 |
880 void RMediaChangeNotifier::CompleteNotifierL(TInt aReason) |
871 void RMediaChangeNotifier::CompleteNotifierL(TInt aReason) |
881 { |
872 { |
882 __MSFNLOG |
873 if (iRegistered) |
883 if (iRegistered) |
874 { |
884 { |
875 TBool mediaChanged = ETrue; |
885 TBool mediaChanged = ETrue; |
876 TPtrC8 pStatus((TUint8*)&mediaChanged,sizeof(TBool)); |
886 TPtrC8 pStatus((TUint8*)&mediaChanged,sizeof(TBool)); |
877 iNotifier.WriteL(0,pStatus); |
887 iNotifier.WriteL(0,pStatus); |
878 iNotifier.Complete(aReason); |
888 iNotifier.Complete(aReason); |
879 iRegistered = EFalse; |
889 iRegistered = EFalse; |
880 } |
890 } |
881 } |
891 } |
|