216 @param aData |
218 @param aData |
217 |
219 |
218 @return ETrue if command was decoded and executed successfully |
220 @return ETrue if command was decoded and executed successfully |
219 */ |
221 */ |
220 TBool CScsiProtocol::DecodePacket(TPtrC8& aData, TUint aLun) |
222 TBool CScsiProtocol::DecodePacket(TPtrC8& aData, TUint aLun) |
221 { |
223 { |
222 __FNLOG("CScsiProtocol::DecodePacket"); |
224 TUint command = aData[1]; |
223 |
225 |
224 TUint8 command = aData[1]; |
226 if (command != ERequestSense) |
225 |
227 { |
226 if (command != ERequestSense) |
228 iSenseInfo.SetSense(TSenseInfo::ENoSense); |
227 { |
229 } |
228 iSenseInfo.SetSense(TSenseInfo::ENoSense); |
230 |
229 } |
231 OstTraceExt2(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_DECODEPACKET, "Command=0x%x LUN=%d", command, aLun); |
230 |
232 switch (command) |
231 __PRINT2(_L("command = 0x%x lun=%d"), command, aLun); |
233 { |
232 switch (command) |
234 case ETestUnitReady: |
233 { |
235 HandleUnitReady(aLun); |
234 case ETestUnitReady: |
236 break; |
235 HandleUnitReady(aLun); |
237 |
236 break; |
238 case ERequestSense: |
237 |
239 HandleRequestSense(aData); |
238 case ERequestSense: |
240 break; |
239 HandleRequestSense(aData); |
241 |
240 break; |
242 case EInquiry: |
241 |
243 HandleInquiry(aData, aLun); |
242 case EInquiry: |
244 break; |
243 HandleInquiry(aData, aLun); |
245 |
244 break; |
246 case EModeSense6: |
245 |
247 HandleModeSense6(aData, aLun); |
246 case EModeSense6: |
248 break; |
247 HandleModeSense6(aData, aLun); |
|
248 break; |
|
249 |
249 |
250 case EModeSense10: |
250 case EModeSense10: |
251 HandleModeSense10(aData, aLun); |
251 HandleModeSense10(aData, aLun); |
252 break; |
252 break; |
253 |
253 |
254 case EStartStopUnit: |
254 case EStartStopUnit: |
255 HandleStartStopUnit(aData, aLun); |
255 HandleStartStopUnit(aData, aLun); |
256 break; |
256 break; |
257 |
257 |
258 case EPreventMediaRemoval: |
258 case EPreventMediaRemoval: |
259 HandlePreventMediaRemoval(aData, aLun); |
259 HandlePreventMediaRemoval(aData, aLun); |
260 break; |
260 break; |
261 |
261 |
262 case EReadCapacity: |
262 case EReadCapacity: |
263 HandleReadCapacity(aData, aLun); |
263 HandleReadCapacity(aData, aLun); |
264 break; |
264 break; |
265 |
265 |
266 case ERead10: |
266 case ERead10: |
267 HandleRead10(aData, aLun); |
267 HandleRead10(aData, aLun); |
268 break; |
268 break; |
269 |
269 |
270 case EWrite10: |
270 case EWrite10: |
271 HandleWrite10(aData,aLun); |
271 HandleWrite10(aData,aLun); |
272 break; |
272 break; |
273 |
273 |
274 case EVerify10: |
274 case EVerify10: |
275 HandleVerify10(aData, aLun); |
275 HandleVerify10(aData, aLun); |
276 break; |
276 break; |
277 |
277 |
278 case EReadFormatCapacities: |
278 case EReadFormatCapacities: |
279 HandleReadFormatCapacities(aLun); |
279 HandleReadFormatCapacities(aLun); |
280 break; |
280 break; |
281 |
281 |
282 default: |
282 default: |
283 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidCmdCode); |
283 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidCmdCode); |
284 } |
284 } |
285 __PRINT1(_L("DecodePacket result = %d"), iSenseInfo.SenseOk()); |
285 return(iSenseInfo.SenseOk()); |
286 return(iSenseInfo.SenseOk()); |
286 } |
287 } |
|
288 |
287 |
289 |
288 |
290 /** |
289 /** |
291 Checks if drive ready |
290 Checks if drive ready |
292 |
291 |
293 @param aLun Logic unit number |
292 @param aLun Logic unit number |
294 @return pointer to drive correspondent to LUN if drive mounted and ready, NULL otherwise |
293 @return pointer to drive correspondent to LUN if drive mounted and ready, NULL otherwise |
295 */ |
294 */ |
296 CMassStorageDrive* CScsiProtocol::GetCheckDrive(TUint aLun) |
295 CMassStorageDrive* CScsiProtocol::GetCheckDrive(TUint aLun) |
297 { |
296 { |
298 __FNLOG("CScsiProtocol::GetCheckDrive"); |
297 TInt err=KErrNone; |
299 TInt err=KErrNone; |
298 |
300 |
299 #ifdef MSDC_MULTITHREADED |
301 #ifdef MSDC_MULTITHREADED |
300 // check for deferred errors |
302 // check for deferred errors |
301 if (iWriteDriveThread->DeferredError()) |
303 if (iWriteDriveThread->DeferredError()) |
302 { |
304 { |
303 iWriteDriveThread->ClearDeferredError(); |
305 iWriteDriveThread->ClearDeferredError(); |
304 iDeferredSenseInfo.SetSense(TSenseInfo::EMediumError); |
306 iDeferredSenseInfo.SetSense(TSenseInfo::EMediumError); |
305 return NULL; |
307 return NULL; |
306 } |
308 } |
307 |
309 |
308 #endif |
310 #endif |
309 |
311 |
310 CMassStorageDrive* drive= iDriveManager.Drive(aLun, err); |
312 CMassStorageDrive* drive= iDriveManager.Drive(aLun, err); |
311 |
313 |
312 if (err !=KErrNone || drive == NULL) |
314 if (err !=KErrNone || drive == NULL) |
313 { |
315 { |
314 OstTrace0(TRACE_SMASSSTORAGE, CSCSIPROTOCOL_GETCHECKDRIVE1, "No drive available"); |
316 __PRINT(_L("No drive available\n")); |
315 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::ELuNotSupported); |
317 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::ELuNotSupported); |
316 return NULL; |
318 return NULL; |
317 } |
319 } |
318 |
320 |
319 CMassStorageDrive::TMountState mountState = drive->MountState(); |
321 CMassStorageDrive::TMountState mountState = drive->MountState(); |
320 |
322 |
321 if (mountState == CMassStorageDrive::EDisconnected || mountState == CMassStorageDrive::EConnecting) |
323 if (mountState == CMassStorageDrive::EDisconnected || mountState == CMassStorageDrive::EConnecting) |
322 { |
324 { |
323 OstTrace0(TRACE_SMASSSTORAGE, CSCSIPROTOCOL_GETCHECKDRIVE2, "Drive disconnected"); |
325 __PRINT(_L("Drive disconnected\n")); |
324 iSenseInfo.SetSense(TSenseInfo::ENotReady, |
326 iSenseInfo.SetSense(TSenseInfo::ENotReady, |
325 TSenseInfo::EMediaNotPresent); |
327 TSenseInfo::EMediaNotPresent); |
326 return NULL; |
328 return NULL; |
327 } |
329 } |
328 |
330 |
329 CMassStorageDrive::TDriveState state = drive->CheckDriveState(); |
331 CMassStorageDrive::TDriveState state = drive->CheckDriveState(); |
330 if (state == CMassStorageDrive::EMediaNotPresent || state == CMassStorageDrive::ELocked) |
332 if (state == CMassStorageDrive::EMediaNotPresent || state == CMassStorageDrive::ELocked) |
331 { |
333 { |
332 OstTrace1(TRACE_SMASSSTORAGE, CSCSIPROTOCOL_GETCHECKDRIVE3, "Media not present or locked. state =0x%X", state); |
334 __PRINT1(_L("Media not present or locked. (state =0x%X)\n"),state); |
333 iSenseInfo.SetSense(TSenseInfo::ENotReady, TSenseInfo::EMediaNotPresent); |
335 iSenseInfo.SetSense(TSenseInfo::ENotReady, TSenseInfo::EMediaNotPresent); |
334 return NULL; |
336 return NULL; |
335 } |
337 } |
336 |
338 |
337 if (drive->IsMediaChanged(ETrue)) //reset "media changed" status |
339 if (drive->IsMediaChanged(ETrue)) //reset "media changed" status |
338 { |
340 { |
339 OstTrace0(TRACE_SMASSSTORAGE, CSCSIPROTOCOL_GETCHECKDRIVE4, "Media was changed"); |
341 __PRINT(_L("Media was changed\n")); |
340 // SAM-2 Section 5.9.5 Unit Attention Condition |
342 // SAM-2 Section 5.9.5 Unit Attention Condition |
341 iSenseInfo.SetSense(TSenseInfo::EUnitAttention, TSenseInfo::ENotReadyToReadyChange); |
343 iSenseInfo.SetSense(TSenseInfo::EUnitAttention, TSenseInfo::ENotReadyToReadyChange); |
342 iDriveManager.Connect(aLun); //publish event to USB app |
344 iDriveManager.Connect(aLun); //publish event to USB app |
343 return NULL; |
345 return NULL; |
344 } |
346 } |
345 |
347 |
346 if (mountState == CMassStorageDrive::EDisconnecting) |
348 if (mountState == CMassStorageDrive::EDisconnecting) |
347 { |
349 { |
348 OstTrace0(TRACE_SMASSSTORAGE, CSCSIPROTOCOL_GETCHECKDRIVE5, "Drive disconnecting"); |
350 __PRINT(_L("Drive disconnecting\n")); |
349 iSenseInfo.SetSense(TSenseInfo::ENotReady, |
351 iSenseInfo.SetSense(TSenseInfo::ENotReady, |
350 TSenseInfo::EMediaNotPresent); |
352 TSenseInfo::EMediaNotPresent); |
351 return NULL; |
353 return NULL; |
352 } |
354 } |
353 |
355 |
354 return drive; |
356 return drive; |
355 } |
357 } |
|
358 |
356 |
359 |
357 |
360 /** |
358 /** |
361 Command Parser for the UNIT READY command (0x00) |
359 Command Parser for the UNIT READY command (0x00) |
362 |
360 |
363 @param aLun Logic unit number |
361 @param aLun Logic unit number |
364 @return ETrue if successful, |
362 @return ETrue if successful, |
365 */ |
363 */ |
366 TBool CScsiProtocol::HandleUnitReady(TUint aLun) |
364 TBool CScsiProtocol::HandleUnitReady(TUint aLun) |
367 { |
365 { |
368 __FNLOG("CScsiProtocol::HandleUnitReady"); |
366 OstTrace0(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_TESTUNITREADY, ">>> TEST UNIT READY"); |
369 #ifdef MSDC_MULTITHREADED |
367 #ifdef MSDC_MULTITHREADED |
370 iWriteDriveThread->WaitForWriteEmpty(); |
368 iWriteDriveThread->WaitForWriteEmpty(); |
371 #endif |
369 #endif |
372 return GetCheckDrive(aLun) ? (TBool)ETrue : (TBool)EFalse; |
370 return GetCheckDrive(aLun) ? (TBool)ETrue : (TBool)EFalse; |
373 } |
371 } |
374 |
372 |
375 |
373 |
376 /** |
374 /** |
377 Command Parser for the REQUEST SENSE command (0x03) |
375 Command Parser for the REQUEST SENSE command (0x03) |
378 |
376 |
379 @return ETrue if successful, |
377 @return ETrue if successful, |
380 */ |
378 */ |
381 TBool CScsiProtocol::HandleRequestSense(TPtrC8& aData) |
379 TBool CScsiProtocol::HandleRequestSense(TPtrC8& aData) |
382 { |
380 { |
383 __FNLOG("CScsiProtocol::HandleRequestSense"); |
381 OstTrace0(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_REQUESTSENSE, ">>> REQUEST SENSE"); |
384 TUint length = aData[5]; |
382 TUint length = aData[5]; |
385 __PRINT1(_L("length = %d\n"), length); |
383 OstTrace1(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_REQUESTSENSE1, " length = %d", length); |
386 |
384 |
387 TPtr8 writeBuf(NULL, 0); |
385 TPtr8 writeBuf(NULL, 0); |
388 iTransport->GetCommandBufPtr(writeBuf, KRequestSenseCommandLength); |
386 iTransport->GetCommandBufPtr(writeBuf, KRequestSenseCommandLength); |
389 writeBuf.FillZ(KRequestSenseCommandLength); |
387 writeBuf.FillZ(KRequestSenseCommandLength); |
390 |
388 |
391 TSenseInfo* senseInfo; |
389 TSenseInfo* senseInfo; |
392 #ifdef MSDC_MULTITHREADED |
390 #ifdef MSDC_MULTITHREADED |
393 if (!iDeferredSenseInfo.SenseOk()) |
391 if (!iDeferredSenseInfo.SenseOk()) |
394 { |
392 { |
395 writeBuf[00] = 0x71; //(deferred errors) |
393 writeBuf[00] = 0x71; //(deferred errors) |
396 senseInfo = &iDeferredSenseInfo; |
394 senseInfo = &iDeferredSenseInfo; |
397 } |
395 } |
398 else |
396 else |
399 { |
397 { |
400 writeBuf[00] = 0x70; //(current errors) |
398 writeBuf[00] = 0x70; //(current errors) |
401 senseInfo = &iSenseInfo; |
399 senseInfo = &iSenseInfo; |
402 } |
400 } |
403 #else |
401 #else |
404 senseInfo = &iSenseInfo; |
402 senseInfo = &iSenseInfo; |
405 writeBuf[00] = 0x70; //(current errors) |
403 writeBuf[00] = 0x70; //(current errors) |
406 #endif |
404 #endif |
407 |
405 |
408 writeBuf[02] = static_cast<TUint8>(senseInfo->iSenseCode & 0x0F); |
406 writeBuf[02] = static_cast<TUint8>(senseInfo->iSenseCode & 0x0F); |
409 |
407 |
410 writeBuf[12] = senseInfo->iAdditional; |
408 writeBuf[12] = senseInfo->iAdditional; |
411 writeBuf[13] = senseInfo->iQualifier; |
409 writeBuf[13] = senseInfo->iQualifier; |
412 if (length<18 && length >=8) |
410 if (length<18 && length >=8) |
413 { |
411 { |
414 writeBuf.SetLength(length); //length of response code data |
412 writeBuf.SetLength(length); //length of response code data |
415 writeBuf[07] = TUint8(length - 8); //additional sence length |
413 writeBuf[07] = TUint8(length - 8); //additional sence length |
416 } |
414 } |
417 else if (length >= KRequestSenseCommandLength) |
415 else if (length >= KRequestSenseCommandLength) |
418 { |
416 { |
419 writeBuf[07] = KRequestSenseCommandLength - 8; // we have max 18 byte to send |
417 writeBuf[07] = KRequestSenseCommandLength - 8; // we have max 18 byte to send |
420 } |
418 } |
421 |
419 |
422 __PRINT4(_L("Response=0x%x Sense=0x%x, Additional=0x%x, Qualifier=0x%x\n"), |
420 OstTraceExt4(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_REQUESTSENSE2, |
423 writeBuf[0], writeBuf[02], writeBuf[12], writeBuf[13]); |
421 " Response=0x%x Sense=0x%x, Additional=0x%x, Qualifier=0x%x", |
424 |
422 (TUint)writeBuf[0], (TUint)writeBuf[02], (TUint)writeBuf[12], (TUint)writeBuf[13]); |
425 TPtrC8 writeBuf1 = writeBuf.Left(length); |
423 |
426 |
424 TPtrC8 writeBuf1 = writeBuf.Left(length); |
427 iTransport->SetupWriteData(writeBuf1); |
425 |
428 |
426 iTransport->SetupWriteData(writeBuf1); |
429 // clear the sense info |
427 |
430 iSenseInfo.SetSense(TSenseInfo::ENoSense); |
428 // clear the sense info |
431 |
429 iSenseInfo.SetSense(TSenseInfo::ENoSense); |
432 #ifdef MSDC_MULTITHREADED |
430 |
433 iDeferredSenseInfo.SetSense(TSenseInfo::ENoSense); |
431 #ifdef MSDC_MULTITHREADED |
434 #endif |
432 iDeferredSenseInfo.SetSense(TSenseInfo::ENoSense); |
435 |
433 #endif |
436 return ETrue; |
434 |
437 } |
435 return ETrue; |
|
436 } |
438 |
437 |
439 |
438 |
440 /** |
439 /** |
441 Command Parser for the INQUIRY command (0x12) |
440 Command Parser for the INQUIRY command (0x12) |
442 |
441 |
443 @param aLun Logic unit number |
442 @param aLun Logic unit number |
444 @return ETrue if successful, |
443 @return ETrue if successful, |
445 */ |
444 */ |
446 TBool CScsiProtocol::HandleInquiry(TPtrC8& aData, TUint aLun ) |
445 TBool CScsiProtocol::HandleInquiry(TPtrC8& aData, TUint aLun ) |
447 { |
446 { |
448 __FNLOG("CScsiProtocol::HandleInquiry"); |
447 OstTrace0(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_INQUIRY, ">>> INQUIRY"); |
449 |
448 TBool cmdDt = aData[2] & 0x2; |
450 TBool cmdDt = aData[2] & 0x2; |
449 TBool evpd = aData[2] & 0x1; |
451 TBool evpd = aData[2] & 0x1; |
450 TUint8 page = aData[3]; |
452 TUint8 page = aData[3]; |
451 if (cmdDt || evpd || page || aLun >= KUsbMsMaxDrives) |
453 if (cmdDt || evpd || page || aLun >= KUsbMsMaxDrives) |
452 { |
454 { |
453 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb); |
455 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb); |
454 return EFalse; |
456 return EFalse; |
455 } |
457 } |
456 |
458 |
457 TPtr8 writeBuf(NULL, 0); |
459 TPtr8 writeBuf(NULL, 0); |
458 iTransport->GetCommandBufPtr(writeBuf, KInquiryCommandLength); |
460 iTransport->GetCommandBufPtr(writeBuf, KInquiryCommandLength); |
459 writeBuf.FillZ(KInquiryCommandLength); |
461 writeBuf.FillZ(KInquiryCommandLength); |
460 |
462 |
461 writeBuf[1] = 0x80; // MSB: RMB : Removable |
463 writeBuf[1] = 0x80; // MSB: RMB : Removable |
462 writeBuf[3] = 0x02; // AERC, TrmTsk, NormACA, Response Data Format |
464 writeBuf[3] = 0x02; // AERC, TrmTsk, NormACA, Response Data Format |
463 writeBuf[4] = 0x1F; // Additional Length |
465 writeBuf[4] = 0x1F; // Additional Length |
464 |
466 |
465 TPtr8 vendorId(&writeBuf[8], 8, 8); // Vendor ID (Vendor Specific/Logged by T10) |
467 TPtr8 vendorId(&writeBuf[8], 8, 8); // Vendor ID (Vendor Specific/Logged by T10) |
466 vendorId.Fill(' ', 8); |
468 vendorId.Fill(' ', 8); |
467 vendorId.Copy(iConfig.iVendorId); |
469 vendorId.Copy(iConfig.iVendorId); |
468 |
470 |
469 TPtr8 productId(&writeBuf[16], 16, 16); // Product ID (Vendor Specific) |
471 TPtr8 productId(&writeBuf[16], 16, 16); // Product ID (Vendor Specific) |
470 productId.Fill(' ', 16); |
472 productId.Fill(' ', 16); |
471 productId.Copy(iConfig.iProductId); |
473 productId.Copy(iConfig.iProductId); |
472 |
474 |
473 TPtr8 productRev(&writeBuf[32], 4, 4); // Product Revision Level (Vendor Specific) |
475 TPtr8 productRev(&writeBuf[32], 4, 4); // Product Revision Level (Vendor Specific) |
474 productRev.Fill(' ', 4); |
476 productRev.Fill(' ', 4); |
475 productRev.Copy(iConfig.iProductRev); |
477 productRev.Copy(iConfig.iProductRev); |
476 |
|
477 OstTraceData(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_INQUIRY1, "Vendor ID %s", vendorId.Ptr(), vendorId.Length()); |
|
478 OstTraceData(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_INQUIRY2, "Product ID %s", productId.Ptr(), productId.Length()); |
|
479 OstTraceData(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_INQUIRY3, "Product Rev %s", productRev.Ptr(), productRev.Length()); |
478 |
480 |
479 TUint length = aData[5]; |
481 TUint length = aData[5]; |
480 |
482 |
481 TPtrC8 writeBuf1 = writeBuf.Left(length); |
483 TPtrC8 writeBuf1 = writeBuf.Left(length); |
482 iTransport->SetupWriteData(writeBuf1); |
484 iTransport->SetupWriteData(writeBuf1); |
483 |
485 |
484 iSenseInfo.SetSense(TSenseInfo::ENoSense); |
486 iSenseInfo.SetSense(TSenseInfo::ENoSense); |
485 return ETrue; |
487 return ETrue; |
486 } |
488 } |
487 |
489 |
488 |
490 |
489 /** |
491 /** |
490 Command Parser for the START STOP UNIT command (0x1B) |
492 Command Parser for the START STOP UNIT command (0x1B) |
491 |
493 |
492 @param aData command data (started form position 1) |
494 @param aData command data (started form position 1) |
493 @param aLun Logic unit number |
495 @param aLun Logic unit number |
494 @return ETrue if successful, TFalse otherwise |
496 @return ETrue if successful, TFalse otherwise |
495 */ |
497 */ |
496 TBool CScsiProtocol::HandleStartStopUnit(TPtrC8& aData, TUint aLun) |
498 TBool CScsiProtocol::HandleStartStopUnit(TPtrC8& aData, TUint aLun) |
497 { |
499 { |
498 __FNLOG("CScsiProtocol::HandleStartStopUnit"); |
500 OstTrace0(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_STARTSTOPUNIT, ">>> START STOP UNIT"); |
499 |
501 const TUint8 KStartMask = 0x01; |
500 const TUint8 KStartMask = 0x01; |
502 const TUint8 KImmedMask = 0x01; |
501 const TUint8 KImmedMask = 0x01; |
503 const TUint8 KLoejMask = 0x02; |
502 const TUint8 KLoejMask = 0x02; |
504 |
503 |
505 TBool immed = aData[2] & KImmedMask ? (TBool)ETrue : (TBool)EFalse; |
504 TBool immed = aData[2] & KImmedMask ? (TBool)ETrue : (TBool)EFalse; |
506 TBool start = aData[5] & KStartMask ? (TBool)ETrue : (TBool)EFalse; |
505 TBool start = aData[5] & KStartMask ? (TBool)ETrue : (TBool)EFalse; |
507 TBool loej = aData[5] & KLoejMask ? (TBool)ETrue : (TBool)EFalse; |
506 TBool loej = aData[5] & KLoejMask ? (TBool)ETrue : (TBool)EFalse; |
508 |
507 |
509 OstTrace1(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_STARTSTOPUNIT1, " IMMED = %d", immed); |
508 __PRINT2(_L("Data %X %X\n"), aData[2], aData[5]); |
510 OstTrace1(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_STARTSTOPUNIT2, " START = %d", start); |
509 __PRINT1(_L("IMMED = %d\n"), immed); |
511 OstTrace1(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_STARTSTOPUNIT3, " LOEJ = %d", loej); |
510 __PRINT1(_L("START = %d\n"), start); |
512 |
511 |
513 TInt err(KErrNone); |
512 __PRINT1(_L("LOEJ = %d\n"), loej); |
514 if (loej) |
513 |
515 { |
514 TInt err(KErrNone); |
516 if(start) //Start unit |
515 if (loej) |
517 { |
516 { |
518 err = iDriveManager.Connect(aLun); |
517 if(start) //Start unit |
|
518 { |
|
519 err = iDriveManager.Connect(aLun); |
|
520 __PRINT(_L("Load media\n")); |
|
521 |
519 |
522 #ifdef USB_TRANSFER_PUBLISHER |
520 #ifdef USB_TRANSFER_PUBLISHER |
523 iBytesRead[aLun] = 0; |
521 iBytesRead[aLun] = 0; |
524 iBytesWritten[aLun] = 0; |
522 iBytesWritten[aLun] = 0; |
525 #endif |
523 #endif |
526 // publish the initial values |
524 // publish the initial values |
527 iWriteTransferPublisher->DoPublishDataTransferredEvent(); |
525 iWriteTransferPublisher->DoPublishDataTransferredEvent(); |
528 iReadTransferPublisher->DoPublishDataTransferredEvent(); |
526 iReadTransferPublisher->DoPublishDataTransferredEvent(); |
529 } |
527 } |
530 else //Stop unit |
528 else //Stop unit |
531 { |
529 { |
532 iDriveManager.SetCritical(aLun, EFalse); |
530 iDriveManager.SetCritical(aLun, EFalse); |
533 err = iDriveManager.Disconnect(aLun); |
531 err = iDriveManager.Disconnect(aLun); |
534 __PRINT(_L("Unload media\n")); |
532 } |
535 } |
533 } |
536 } |
534 |
537 |
535 if (err !=KErrNone) //actually we have error here only if the LUN is incorrect |
538 if (err !=KErrNone) //actually we have error here only if the LUN is incorrect |
536 { |
539 { |
537 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::ELuNotSupported); |
540 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::ELuNotSupported); |
538 return EFalse; |
541 return EFalse; |
539 } |
542 } |
540 if (immed) |
543 if (immed) |
541 { |
544 { |
542 return ETrue; |
545 return ETrue; |
543 } |
546 } |
544 |
547 |
545 CMassStorageDrive* drive= iDriveManager.Drive(aLun, err); |
548 CMassStorageDrive* drive= iDriveManager.Drive(aLun, err); |
546 |
549 |
547 if (err !=KErrNone || drive == NULL) |
550 if (err !=KErrNone || drive == NULL) |
548 { |
551 { |
549 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::ELuNotSupported); |
552 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::ELuNotSupported); |
550 return EFalse; |
553 return EFalse; |
551 } |
554 } |
552 |
555 |
553 TInt timeLeft (20); // 1 sec timeout |
556 TInt timeLeft (20); // 1 sec timeout |
554 CMassStorageDrive::TMountState mountState; |
557 CMassStorageDrive::TMountState mountState; |
555 |
558 |
556 do |
559 do |
557 { |
560 { |
558 User::After(1000 * 50); // 50 mSec |
561 User::After(1000 * 50); // 50 mSec |
559 --timeLeft; |
562 --timeLeft; |
560 mountState = drive->MountState(); |
563 mountState = drive->MountState(); |
561 |
564 |
562 if ((!start && mountState != CMassStorageDrive::EConnected) |
565 if ((!start && mountState != CMassStorageDrive::EConnected) |
563 || |
566 || |
564 (start && |
567 (start && |
565 (mountState == CMassStorageDrive::EDisconnecting || |
568 (mountState == CMassStorageDrive::EDisconnecting || |
566 mountState == CMassStorageDrive::EConnected)) |
569 mountState == CMassStorageDrive::EConnected)) |
567 ) |
570 ) |
568 { |
571 { |
569 return ETrue; |
572 return ETrue; |
570 } |
573 } |
571 } while (timeLeft>0); |
574 } while (timeLeft>0); |
572 |
575 |
573 //timeout happend |
576 //timeout happend |
574 iSenseInfo.SetSense(TSenseInfo::ENotReady, |
577 iSenseInfo.SetSense(TSenseInfo::ENotReady, |
575 TSenseInfo::EAscLogicalUnitDoesNotRespondToSelection); |
578 TSenseInfo::EAscLogicalUnitDoesNotRespondToSelection); |
576 return EFalse; |
579 return EFalse; |
577 } |
580 } |
|
581 |
578 |
582 |
579 |
583 /** |
580 /** |
584 Command Parser for the PREVENT/ALLOW MEDIA REMOVAL command (0x1E) |
581 Command Parser for the PREVENT/ALLOW MEDIA REMOVAL command (0x1E) |
585 |
582 |
586 @param aData command data (started form position 1) |
583 @param aData command data (started form position 1) |
587 @param aLun Logic unit number |
584 @param aLun Logic unit number |
588 @return ETrue if successful. |
585 @return ETrue if successful. |
589 */ |
586 */ |
590 TBool CScsiProtocol::HandlePreventMediaRemoval(TPtrC8& aData, TUint aLun) |
587 TBool CScsiProtocol::HandlePreventMediaRemoval(TPtrC8& aData, TUint aLun) |
591 { |
588 { |
592 __FNLOG("CScsiProtocol::HandlePreventMediaRemoval"); |
589 OstTrace0(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_PREVENTMEDIAREMOVAL, ">>> PREVENT MEDIA REMOVAL"); |
593 CMassStorageDrive* drive=GetCheckDrive(aLun); |
590 CMassStorageDrive* drive=GetCheckDrive(aLun); |
594 |
591 |
595 if (drive == NULL) |
592 if (drive == NULL) |
596 { |
593 { |
597 return EFalse; |
594 return EFalse; |
598 } |
595 } |
599 |
596 |
600 TInt prevent = aData[5] & 0x01; |
597 TInt prevent = aData[5] & 0x01; |
601 __PRINT1(_L("prevent = %d\n"), prevent); |
598 OstTrace1(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_PREVENTMEDIAREMOVAL1, " prevent = %d", prevent); |
602 iDriveManager.SetCritical(aLun, prevent); |
599 iDriveManager.SetCritical(aLun, prevent); |
603 |
600 return ETrue; |
604 return ETrue; |
601 } |
605 } |
|
606 |
602 |
607 |
603 |
608 /** Cancel active state, Invoked by transnport when it stops */ |
604 /** Cancel active state, Invoked by transnport when it stops */ |
609 TInt CScsiProtocol::Cancel() |
605 TInt CScsiProtocol::Cancel() |
610 { |
606 { |
611 iDriveManager.SetCritical(CDriveManager::KAllLuns, EFalse); |
607 iDriveManager.SetCritical(CDriveManager::KAllLuns, EFalse); |
612 return KErrNone; |
608 return KErrNone; |
613 } |
609 } |
614 |
610 |
615 |
611 |
616 TBool CScsiProtocol::HandleReadFormatCapacities(TUint aLun) |
612 TBool CScsiProtocol::HandleReadFormatCapacities(TUint aLun) |
617 /** |
613 /** |
618 * Command Parser for the READ FORMAT CAPACITIES command (0x23) |
614 * Command Parser for the READ FORMAT CAPACITIES command (0x23) |
619 * |
615 * |
620 * @return ETrue if successful, else a standard Symbian OS error code. |
616 * @return ETrue if successful, else a standard Symbian OS error code. |
621 */ |
617 */ |
622 { |
618 { |
623 __FNLOG("CScsiProtocol::HandleReadFormatCapacities"); |
619 OstTrace0(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_READFORMATCAPACITIES, ">>> READ FORMAT CAPACITIES"); |
624 |
620 CMassStorageDrive* drive=GetCheckDrive(aLun); |
625 CMassStorageDrive* drive=GetCheckDrive(aLun); |
621 |
626 |
622 if (drive == NULL) |
627 if (drive == NULL) |
623 { |
628 { |
624 return EFalse; |
629 return EFalse; |
625 } |
630 } |
626 |
631 |
627 TLocalDriveCapsV4 driveInfo; |
632 TLocalDriveCapsV4 driveInfo; |
628 |
633 |
629 TInt err = drive->Caps(driveInfo); |
634 TInt err = drive->Caps(driveInfo); |
630 |
635 |
631 if(err != KErrNone) |
636 if(err != KErrNone) |
632 { |
637 { |
633 OstTrace1(TRACE_SMASSSTORAGE, CSCSIPROTOCOL_HANDLEREADFORMATCAPACITIES, "Can't obtain drive Caps. Err=%d", err); |
638 __PRINT1(_L("Can't obtain drive Caps. Err=%d \n"),err); |
634 iSenseInfo.SetSense(TSenseInfo::ENotReady, TSenseInfo::EMediaNotPresent); |
639 iSenseInfo.SetSense(TSenseInfo::ENotReady, TSenseInfo::EMediaNotPresent); |
635 return EFalse; |
640 return EFalse; |
636 } |
641 } |
637 |
642 |
638 TInt64 driveBlocks = (driveInfo.iDriveAtt & KDriveAttLogicallyRemovable) ? driveInfo.iSize : driveInfo.MediaSizeInBytes(); |
643 TInt64 driveBlocks = (driveInfo.iDriveAtt & KDriveAttLogicallyRemovable) ? driveInfo.iSize : driveInfo.MediaSizeInBytes(); |
639 driveBlocks /= MAKE_TINT64(0, KDefaultBlockSize); |
644 driveBlocks /= MAKE_TINT64(0, KDefaultBlockSize); |
640 |
645 |
641 TPtr8 writeBuf(NULL, 0); |
646 TPtr8 writeBuf(NULL, 0); |
642 iTransport->GetCommandBufPtr(writeBuf, KReadFormatCapacitiesCommandLength); |
647 iTransport->GetCommandBufPtr(writeBuf, KReadFormatCapacitiesCommandLength); |
643 writeBuf.FillZ(KReadFormatCapacitiesCommandLength); |
648 writeBuf.FillZ(KReadFormatCapacitiesCommandLength); |
644 |
649 |
645 writeBuf[3] = 0x08; // Capacity List Length |
650 writeBuf[3] = 0x08; // Capacity List Length |
646 |
651 |
647 TUint32 numBlocks = I64LOW(driveBlocks); |
652 TUint32 numBlocks = I64LOW(driveBlocks); |
648 |
653 |
649 writeBuf[4] = static_cast<TUint8>((numBlocks & 0xFF000000) >> 24); // Number of blocks |
654 writeBuf[4] = static_cast<TUint8>((numBlocks & 0xFF000000) >> 24); // Number of blocks |
650 writeBuf[5] = static_cast<TUint8>((numBlocks & 0x00FF0000) >> 16); // |
655 writeBuf[5] = static_cast<TUint8>((numBlocks & 0x00FF0000) >> 16); // |
651 writeBuf[6] = static_cast<TUint8>((numBlocks & 0x0000FF00) >> 8); // |
656 writeBuf[6] = static_cast<TUint8>((numBlocks & 0x0000FF00) >> 8); // |
652 writeBuf[7] = static_cast<TUint8>((numBlocks & 0x000000FF)); // |
657 writeBuf[7] = static_cast<TUint8>((numBlocks & 0x000000FF)); // |
653 |
658 |
654 writeBuf[8] = 0x02; // Formatted size |
659 writeBuf[8] = 0x02; // Formatted size |
655 |
660 |
656 writeBuf[9] = 0x00; // 512 Byte Blocks |
661 writeBuf[9] = 0x00; // 512 Byte Blocks |
657 writeBuf[10] = 0x02; // |
662 writeBuf[10] = 0x02; // |
658 writeBuf[11] = 0x00; // |
663 writeBuf[11] = 0x00; // |
659 |
664 |
660 TPtrC8 writeBuf1 = writeBuf; |
665 TPtrC8 writeBuf1 = writeBuf; |
661 |
666 |
662 iTransport->SetupWriteData(writeBuf1); |
667 iTransport->SetupWriteData(writeBuf1); |
663 |
668 |
664 return ETrue; |
669 return ETrue; |
665 } |
670 } |
|
671 |
666 |
672 |
667 |
673 /** |
668 /** |
674 Command Parser for the READ CAPACITY(10) command (0x25) |
669 Command Parser for the READ CAPACITY(10) command (0x25) |
675 |
|
676 @param aData command data (started form position 1) |
|
677 @param aLun Logic unit number |
|
678 @return ETrue if successful. |
|
679 */ |
|
680 TBool CScsiProtocol::HandleReadCapacity(TPtrC8& aData, TUint aLun) |
|
681 { |
|
682 __FNLOG("CScsiProtocol::HandleReadCapacity"); |
|
683 CMassStorageDrive* drive=GetCheckDrive(aLun); |
|
684 |
|
685 if (drive == NULL) |
|
686 { |
|
687 return EFalse; |
|
688 } |
|
689 |
|
690 TInt pmi = aData[9] & 0x01; |
|
691 TInt lba = aData[3] | aData[4] | aData[5] | aData[6]; |
|
692 |
|
693 if (pmi || lba) //do not support partial medium indicator |
|
694 { |
|
695 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb); |
|
696 return EFalse; |
|
697 } |
|
698 |
|
699 TLocalDriveCapsV4 driveInfo; |
|
700 |
|
701 TInt err = drive->Caps(driveInfo); |
|
702 |
|
703 if(err != KErrNone) |
|
704 { |
|
705 __PRINT1(_L("Can't obtain drive Caps. Err=%d \n"),err); |
|
706 iSenseInfo.SetSense(TSenseInfo::ENotReady, TSenseInfo::EMediaNotPresent); |
|
707 return EFalse; |
|
708 } |
|
709 |
|
710 TInt64 driveBlocks = 0; |
|
711 if (driveInfo.iDriveAtt & KDriveAttLogicallyRemovable) |
|
712 { |
|
713 // Partition Access only |
|
714 driveBlocks = driveInfo.iSize / MAKE_TINT64(0, KDefaultBlockSize); |
|
715 } |
|
716 else |
|
717 { |
|
718 // whole Media Access |
|
719 driveBlocks = driveInfo.MediaSizeInBytes() / MAKE_TINT64(0, KDefaultBlockSize) - 1; |
|
720 } |
|
721 |
|
722 |
|
723 TPtr8 writeBuf(NULL, 0); |
|
724 iTransport->GetCommandBufPtr(writeBuf, KReadCapacityCommandLength); |
|
725 writeBuf.FillZ(KReadCapacityCommandLength); |
|
726 |
|
727 if (I64HIGH(driveBlocks) == 0) |
|
728 { |
|
729 TUint32 numBlocks = I64LOW(driveBlocks); |
|
730 |
|
731 __PRINT2(_L("Block size=%d, NumBlocks=%d\n"), KDefaultBlockSize, numBlocks); |
|
732 writeBuf[0] = static_cast<TUint8>((numBlocks & 0xFF000000) >> 24); // Number of blocks |
|
733 writeBuf[1] = static_cast<TUint8>((numBlocks & 0x00FF0000) >> 16); |
|
734 writeBuf[2] = static_cast<TUint8>((numBlocks & 0x0000FF00) >> 8); |
|
735 writeBuf[3] = static_cast<TUint8>((numBlocks & 0x000000FF)); |
|
736 } |
|
737 else |
|
738 { |
|
739 writeBuf[0] = writeBuf[1] = writeBuf[2] = writeBuf[3] = 0xFF; // indicate that size more then )0xFFFFFFFF |
|
740 } |
|
741 |
|
742 writeBuf[4] = static_cast<TUint8>((KDefaultBlockSize & 0xFF000000) >> 24); // Block Size |
|
743 writeBuf[5] = static_cast<TUint8>((KDefaultBlockSize & 0x00FF0000) >> 16); |
|
744 writeBuf[6] = static_cast<TUint8>((KDefaultBlockSize & 0x0000FF00) >> 8); |
|
745 writeBuf[7] = static_cast<TUint8>((KDefaultBlockSize & 0x000000FF)); |
|
746 |
|
747 TPtrC8 writeBuf1 = writeBuf; |
|
748 iTransport->SetupWriteData(writeBuf1); |
|
749 |
|
750 return KErrNone; |
|
751 } |
|
752 |
|
753 |
|
754 /** |
|
755 Command Parser for the READ10 command (0x28) |
|
756 |
670 |
757 @param aData command data (started form position 1) |
671 @param aData command data (started form position 1) |
758 @param aLun Logic unit number |
672 @param aLun Logic unit number |
759 @return ETrue if successful. |
673 @return ETrue if successful. |
760 */ |
674 */ |
761 TBool CScsiProtocol::HandleRead10(TPtrC8& aData, TUint aLun) |
675 TBool CScsiProtocol::HandleReadCapacity(TPtrC8& aData, TUint aLun) |
762 { |
676 { |
763 __FNLOG("CScsiProtocol::HandleRead10"); |
677 OstTrace0(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_READCAPACITY, ">>> READ CAPACITY"); |
764 CMassStorageDrive* drive = GetCheckDrive(aLun); |
678 CMassStorageDrive* drive=GetCheckDrive(aLun); |
765 if (drive == NULL) |
679 |
766 { |
680 if (drive == NULL) |
767 return EFalse; |
681 { |
768 } |
682 return EFalse; |
769 TInt rdProtect = aData[2] >> 5; |
683 } |
770 if (rdProtect) |
684 |
771 { |
685 TInt pmi = aData[9] & 0x01; |
772 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb); |
686 TInt lba = aData[3] | aData[4] | aData[5] | aData[6]; |
773 return EFalse; |
687 |
774 } |
688 if (pmi || lba) //do not support partial medium indicator |
775 |
689 { |
776 const TUint32 lba = LBA(aData); |
690 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb); |
777 const TUint16 len = LEN(aData); |
691 return EFalse; |
778 |
692 } |
779 __PRINT2(_L("READ(10) : LBA = 0x%x, Length = %d (blocks)\n"), lba, len); |
693 |
780 |
694 TLocalDriveCapsV4 driveInfo; |
781 if (!len) |
695 |
782 { |
696 TInt err = drive->Caps(driveInfo); |
783 return ETrue; // do nothing - this is not an error |
697 |
784 } |
698 if(err != KErrNone) |
785 |
699 { |
786 TLocalDriveCapsV4 driveInfo; |
700 OstTrace1(TRACE_SMASSSTORAGE, CSCSIPROTOCOL_HANDLEREADCAPACITY1, "ERROR: Can't obtain drive Caps Err=%d", err); |
787 TInt err = drive->Caps(driveInfo); |
701 iSenseInfo.SetSense(TSenseInfo::ENotReady, TSenseInfo::EMediaNotPresent); |
788 if (err != KErrNone) |
702 return EFalse; |
789 { |
703 } |
790 __PRINT1(_L("Can't obtain drive Caps. Err=%d \n"), err); |
704 |
791 iSenseInfo.SetSense(TSenseInfo::ENotReady, TSenseInfo::EMediaNotPresent); |
705 TInt64 driveBlocks = 0; |
792 return EFalse; |
706 if (driveInfo.iDriveAtt & KDriveAttLogicallyRemovable) |
793 } |
707 { |
794 |
708 // Partition Access only |
795 const TInt64 bOffset = MAKE_TINT64(0, lba) * KDefaultBlockSize; |
709 driveBlocks = driveInfo.iSize / MAKE_TINT64(0, KDefaultBlockSize); |
796 const TInt bLength = len * KDefaultBlockSize; |
710 } |
797 const TInt64 theEnd = bOffset + MAKE_TINT64(0, bLength); |
711 else |
798 const TInt64 mediaSize = (driveInfo.iDriveAtt & KDriveAttLogicallyRemovable) ? driveInfo.iSize : driveInfo.MediaSizeInBytes() ; |
712 { |
799 |
713 // whole Media Access |
800 if (theEnd > mediaSize) //check if media big enough for this request |
714 driveBlocks = driveInfo.MediaSizeInBytes() / MAKE_TINT64(0, KDefaultBlockSize) - 1; |
801 { |
715 } |
802 __PRINT(_L("err - Request ends out of media\n")); |
716 |
803 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::ELbaOutOfRange); |
717 |
804 return EFalse; |
718 TPtr8 writeBuf(NULL, 0); |
805 } |
719 iTransport->GetCommandBufPtr(writeBuf, KReadCapacityCommandLength); |
806 |
720 writeBuf.FillZ(KReadCapacityCommandLength); |
807 #ifdef MSDC_MULTITHREADED |
721 |
808 iWriteDriveThread->WaitForWriteEmpty(); |
722 if (I64HIGH(driveBlocks) == 0) |
809 |
723 { |
810 // check if our buffer can hold requested data |
724 TUint32 numBlocks = I64LOW(driveBlocks); |
811 if (iReadDriveThread->iThreadContext->MaxBufferLength() < bLength) |
725 |
812 { |
726 OstTraceExt2(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_HANDLEREADCAPACITY2, |
813 __PRINT(_L("err - Buffer too small\n")); |
727 " Block size=0x%x, NumBlocks=0x%x", |
814 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb); |
728 KDefaultBlockSize, numBlocks); |
815 return EFalse; |
729 writeBuf[0] = static_cast<TUint8>((numBlocks & 0xFF000000) >> 24); // Number of blocks |
816 } |
730 writeBuf[1] = static_cast<TUint8>((numBlocks & 0x00FF0000) >> 16); |
817 |
731 writeBuf[2] = static_cast<TUint8>((numBlocks & 0x0000FF00) >> 8); |
818 // Optimisation note : If the host is reading from sectors it just wrote to, |
732 writeBuf[3] = static_cast<TUint8>((numBlocks & 0x000000FF)); |
819 // then we have to force a cache-miss so that the real data is read from the |
733 } |
820 // drive. It would be possible to service the read from the write buffers, |
734 else |
821 // but as the host is probably trying to verify the write data, we don't do |
735 { |
822 // that for now. |
736 writeBuf[0] = writeBuf[1] = writeBuf[2] = writeBuf[3] = 0xFF; // indicate that size more then )0xFFFFFFFF |
823 if (!iReadDriveThread->ReadDriveData(drive, bOffset, bLength, iWriteDriveThread->IsRecentlyWritten(bOffset,bLength))) |
737 } |
824 { |
738 |
825 iSenseInfo.SetSense(TSenseInfo::ENotReady, TSenseInfo::EMediaNotPresent); |
739 writeBuf[4] = static_cast<TUint8>((KDefaultBlockSize & 0xFF000000) >> 24); // Block Size |
826 return EFalse; |
740 writeBuf[5] = static_cast<TUint8>((KDefaultBlockSize & 0x00FF0000) >> 16); |
827 } |
741 writeBuf[6] = static_cast<TUint8>((KDefaultBlockSize & 0x0000FF00) >> 8); |
828 |
742 writeBuf[7] = static_cast<TUint8>((KDefaultBlockSize & 0x000000FF)); |
829 iWriteDriveThread->SetCommandWrite10(EFalse); |
743 |
830 TBlockDesc* &desc = iReadDriveThread->iThreadContext->iBuffer.iDescReadPtr; |
744 TPtrC8 writeBuf1 = writeBuf; |
831 TPtrC8 writeBuf1 = desc->iBuf; |
745 iTransport->SetupWriteData(writeBuf1); |
832 #else |
746 |
833 |
747 return KErrNone; |
834 TPtr8 writeBuf(NULL, 0); |
748 } |
835 iTransport->GetReadDataBufPtr(writeBuf); |
749 |
836 // check if our buffer can hold requested data |
750 |
837 if (writeBuf.MaxLength() < bLength) |
751 /** |
838 { |
752 Command Parser for the READ10 command (0x28) |
839 __PRINT(_L("err - Buffer too small\n")); |
|
840 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb); |
|
841 return EFalse; |
|
842 } |
|
843 |
|
844 err = drive->Read(bOffset, bLength, writeBuf, drive->IsWholeMediaAccess()); |
|
845 |
|
846 if (err != KErrNone) |
|
847 { |
|
848 __PRINT1(_L("Read failed, err=%d\n"), err); |
|
849 iSenseInfo.SetSense(TSenseInfo::ENotReady, TSenseInfo::EMediaNotPresent); |
|
850 return EFalse; |
|
851 } |
|
852 |
|
853 TPtrC8 writeBuf1 = writeBuf; |
|
854 #endif // MSDC_MULTITHREADED |
|
855 #ifdef USB_TRANSFER_PUBLISHER |
|
856 iBytesRead[aLun] += writeBuf1.Length(); |
|
857 #endif |
|
858 iReadTransferPublisher->StartTimer(); |
|
859 |
|
860 // Set up data write to the host |
|
861 iTransport->SetupWriteData(writeBuf1); |
|
862 |
|
863 return ETrue; |
|
864 } |
|
865 |
|
866 |
|
867 /** |
|
868 Command Parser for the WRITE(10) command (0x2A) |
|
869 |
753 |
870 @param aData command data (started form position 1) |
754 @param aData command data (started form position 1) |
871 @param aLun Logic unit number |
755 @param aLun Logic unit number |
872 @return ETrue if successful. |
756 @return ETrue if successful. |
873 */ |
757 */ |
874 TBool CScsiProtocol::HandleWrite10(TPtrC8& aData, TUint aLun) |
758 TBool CScsiProtocol::HandleRead10(TPtrC8& aData, TUint aLun) |
875 { |
759 { |
876 __FNLOG("CScsiProtocol::HandleWrite10"); |
760 OstTrace0(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_READ10, ">>> READ(10)"); |
877 CMassStorageDrive* drive = GetCheckDrive(aLun); |
761 CMassStorageDrive* drive = GetCheckDrive(aLun); |
878 if (drive == NULL) |
762 if (drive == NULL) |
879 { |
763 { |
880 return EFalse; |
764 return EFalse; |
881 } |
765 } |
882 TInt wrProtect = aData[2] >> 5; |
766 TInt rdProtect = aData[2] >> 5; |
883 if (wrProtect) |
767 if (rdProtect) |
884 { |
768 { |
885 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb); |
769 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb); |
886 return EFalse; |
770 return EFalse; |
887 } |
771 } |
888 |
772 |
889 const TUint32 lba = LBA(aData); |
773 const TUint32 lba = LBA(aData); |
890 const TUint16 len = LEN(aData); |
774 const TUint32 len = LEN(aData); |
891 __PRINT2(_L("WRITE(10) : LBA = 0x%x, Length = %d (blocks)\n"), lba, len); |
775 |
892 if (!len) |
776 OstTraceExt2(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_HANDLEREAD10_1, |
893 { |
777 " LBA = 0x%x Transfer Len = 0x%x", lba, len); |
894 return ETrue; // do nothing - this is not an error |
778 |
895 } |
779 if (!len) |
896 |
780 { |
897 TLocalDriveCapsV4 driveInfo; |
781 return ETrue; // do nothing - this is not an error |
898 TInt err = drive->Caps(driveInfo); |
782 } |
899 if (err != KErrNone) |
783 |
900 { |
784 TLocalDriveCapsV4 driveInfo; |
901 __PRINT1(_L("Can't obtain drive Caps. Err=%d \n"), err); |
785 TInt err = drive->Caps(driveInfo); |
902 iSenseInfo.SetSense(TSenseInfo::ENotReady, TSenseInfo::EMediaNotPresent); |
786 if (err != KErrNone) |
903 return EFalse; |
787 { |
904 } |
788 OstTrace1(TRACE_SMASSSTORAGE, CSCSIPROTOCOL_HANDLEREAD10_2, "Can't obtain drive Caps. Err=%d", err); |
905 if (driveInfo.iMediaAtt & KMediaAttWriteProtected || |
789 iSenseInfo.SetSense(TSenseInfo::ENotReady, TSenseInfo::EMediaNotPresent); |
906 driveInfo.iMediaAtt & KMediaAttLocked) |
790 return EFalse; |
907 { |
791 } |
908 iSenseInfo.SetSense(TSenseInfo::EDataProtection, TSenseInfo::EWriteProtected); |
792 |
909 return EFalse; |
793 const TInt64 bOffset = MAKE_TINT64(0, lba) * KDefaultBlockSize; |
910 } |
794 const TInt bLength = len * KDefaultBlockSize; |
911 |
795 const TInt64 theEnd = bOffset + MAKE_TINT64(0, bLength); |
912 const TInt64 bOffset = MAKE_TINT64(0, lba) * KDefaultBlockSize; |
796 const TInt64 mediaSize = (driveInfo.iDriveAtt & KDriveAttLogicallyRemovable) ? driveInfo.iSize : driveInfo.MediaSizeInBytes() ; |
913 iBytesRemain = len * KDefaultBlockSize; |
797 |
914 const TInt64 theEnd = bOffset + MAKE_TINT64(0, iBytesRemain); |
798 if (theEnd > mediaSize) //check if media big enough for this request |
915 const TInt64 mediaSize = (driveInfo.iDriveAtt & KDriveAttLogicallyRemovable) ? driveInfo.iSize : driveInfo.MediaSizeInBytes() ; |
799 { |
916 |
800 OstTrace0(TRACE_SMASSSTORAGE, CSCSIPROTOCOL_HANDLEREAD10_3, "ERROR: Requested size is out of media range"); |
917 if (theEnd > mediaSize) //check if media big enough for this request |
801 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::ELbaOutOfRange); |
918 { |
802 return EFalse; |
919 __PRINT(_L("err - Request ends out of media\n")); |
803 } |
920 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::ELbaOutOfRange); |
804 |
921 return EFalse; |
805 #ifdef MSDC_MULTITHREADED |
922 } |
806 iWriteDriveThread->WaitForWriteEmpty(); |
923 |
807 |
924 #ifdef MSDC_MULTITHREADED |
808 // check if our buffer can hold requested data |
925 iWriteDriveThread->SetCommandWrite10(ETrue); |
809 if (iReadDriveThread->iThreadContext->MaxBufferLength() < bLength) |
926 #endif |
810 { |
927 |
811 OstTrace0(TRACE_SMASSSTORAGE, CSCSIPROTOCOL_HANDLEREAD10_4, "ERROR: Buffer too small"); |
928 // Set up the first request for data from the host - either |
812 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb); |
929 // KMaxBufSize or the entire transfer length, whichever is smallest. |
813 return EFalse; |
930 TUint thisLength = (iBytesRemain > KMaxBufSize) ? KMaxBufSize : iBytesRemain; |
814 } |
931 thisLength = (thisLength > iMediaWriteSize) ? iMediaWriteSize : thisLength; |
815 |
932 |
816 // Optimisation note : If the host is reading from sectors it just wrote to, |
933 iOffset = bOffset; |
817 // then we have to force a cache-miss so that the real data is read from the |
934 iLastCommand = EWrite10; |
818 // drive. It would be possible to service the read from the write buffers, |
935 iLastLun = aLun; |
819 // but as the host is probably trying to verify the write data, we don't do |
936 |
820 // that for now. |
937 iWriteTransferPublisher->StartTimer(); |
821 if (!iReadDriveThread->ReadDriveData(drive, bOffset, bLength, iWriteDriveThread->IsRecentlyWritten(bOffset,bLength))) |
938 iTransport->SetupReadData(thisLength); |
822 { |
939 |
823 iSenseInfo.SetSense(TSenseInfo::ENotReady, TSenseInfo::EMediaNotPresent); |
940 return ETrue; |
824 return EFalse; |
941 } |
825 } |
942 |
826 |
943 |
827 iWriteDriveThread->SetCommandWrite10(EFalse); |
944 /** |
828 TBlockDesc* &desc = iReadDriveThread->iThreadContext->iBuffer.iDescReadPtr; |
945 Command Parser for the VERIFY(10) command (0x2F) |
829 TPtrC8 writeBuf1 = desc->iBuf; |
|
830 #else |
|
831 |
|
832 TPtr8 writeBuf(NULL, 0); |
|
833 iTransport->GetReadDataBufPtr(writeBuf); |
|
834 // check if our buffer can hold requested data |
|
835 if (writeBuf.MaxLength() < bLength) |
|
836 { |
|
837 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb); |
|
838 return EFalse; |
|
839 } |
|
840 |
|
841 err = drive->Read(bOffset, bLength, writeBuf, drive->IsWholeMediaAccess()); |
|
842 |
|
843 if (err != KErrNone) |
|
844 { |
|
845 OstTrace1(TRACE_SMASSSTORAGE, CSCSIPROTOCOL_HANDLEREAD10_5, "ERROR: Read failed err=%d", err); |
|
846 iSenseInfo.SetSense(TSenseInfo::ENotReady, TSenseInfo::EMediaNotPresent); |
|
847 return EFalse; |
|
848 } |
|
849 |
|
850 TPtrC8 writeBuf1 = writeBuf; |
|
851 #endif // MSDC_MULTITHREADED |
|
852 #ifdef USB_TRANSFER_PUBLISHER |
|
853 iBytesRead[aLun] += writeBuf1.Length(); |
|
854 #endif |
|
855 iReadTransferPublisher->StartTimer(); |
|
856 |
|
857 // Set up data write to the host |
|
858 iTransport->SetupWriteData(writeBuf1); |
|
859 |
|
860 return ETrue; |
|
861 } |
|
862 |
|
863 |
|
864 /** |
|
865 Command Parser for the WRITE(10) command (0x2A) |
946 |
866 |
947 @param aData command data (started form position 1) |
867 @param aData command data (started form position 1) |
948 @param aLun Logic unit number |
868 @param aLun Logic unit number |
949 @return ETrue if successful. |
869 @return ETrue if successful. |
950 */ |
870 */ |
|
871 TBool CScsiProtocol::HandleWrite10(TPtrC8& aData, TUint aLun) |
|
872 { |
|
873 OstTrace0(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_WRITE10, ">>> WRITE(10)"); |
|
874 CMassStorageDrive* drive = GetCheckDrive(aLun); |
|
875 if (drive == NULL) |
|
876 { |
|
877 return EFalse; |
|
878 } |
|
879 TInt wrProtect = aData[2] >> 5; |
|
880 if (wrProtect) |
|
881 { |
|
882 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb); |
|
883 return EFalse; |
|
884 } |
|
885 |
|
886 const TUint32 lba = LBA(aData); |
|
887 const TUint32 len = LEN(aData); |
|
888 OstTraceExt2(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_HANDLEWRITE10_1, "LBA = 0x%x, Transfer Len = 0x%x", lba, len); |
|
889 if (!len) |
|
890 { |
|
891 return ETrue; // do nothing - this is not an error |
|
892 } |
|
893 |
|
894 TLocalDriveCapsV4 driveInfo; |
|
895 TInt err = drive->Caps(driveInfo); |
|
896 if (err != KErrNone) |
|
897 { |
|
898 OstTrace1(TRACE_SMASSSTORAGE, CSCSIPROTOCOL_WRITE10_2, "ERROR: Can't obtain drive Caps Err=%d", err); |
|
899 iSenseInfo.SetSense(TSenseInfo::ENotReady, TSenseInfo::EMediaNotPresent); |
|
900 return EFalse; |
|
901 } |
|
902 if (driveInfo.iMediaAtt & KMediaAttWriteProtected || |
|
903 driveInfo.iMediaAtt & KMediaAttLocked) |
|
904 { |
|
905 iSenseInfo.SetSense(TSenseInfo::EDataProtection, TSenseInfo::EWriteProtected); |
|
906 return EFalse; |
|
907 } |
|
908 |
|
909 const TInt64 bOffset = MAKE_TINT64(0, lba) * KDefaultBlockSize; |
|
910 iBytesRemain = len * KDefaultBlockSize; |
|
911 const TInt64 theEnd = bOffset + MAKE_TINT64(0, iBytesRemain); |
|
912 const TInt64 mediaSize = (driveInfo.iDriveAtt & KDriveAttLogicallyRemovable) ? driveInfo.iSize : driveInfo.MediaSizeInBytes() ; |
|
913 |
|
914 if (theEnd > mediaSize) //check if media big enough for this request |
|
915 { |
|
916 OstTrace0(TRACE_SMASSSTORAGE, CSCSIPROTOCOL_HANDLEWRITE10_3, "Requested size is out of media range"); |
|
917 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::ELbaOutOfRange); |
|
918 return EFalse; |
|
919 } |
|
920 |
|
921 #ifdef MSDC_MULTITHREADED |
|
922 iWriteDriveThread->SetCommandWrite10(ETrue); |
|
923 #endif |
|
924 |
|
925 // Set up the first request for data from the host - either |
|
926 // KMaxBufSize or the entire transfer length, whichever is smallest. |
|
927 TUint thisLength = (iBytesRemain > KMaxBufSize) ? KMaxBufSize : iBytesRemain; |
|
928 thisLength = (thisLength > iMediaWriteSize) ? iMediaWriteSize : thisLength; |
|
929 |
|
930 iOffset = bOffset; |
|
931 iLastCommand = EWrite10; |
|
932 iLastLun = aLun; |
|
933 |
|
934 iWriteTransferPublisher->StartTimer(); |
|
935 iTransport->SetupReadData(thisLength); |
|
936 |
|
937 return ETrue; |
|
938 } |
|
939 |
|
940 |
|
941 /** |
|
942 Command Parser for the VERIFY(10) command (0x2F) |
|
943 |
|
944 @param aData command data (started form position 1) |
|
945 @param aLun Logic unit number |
|
946 @return ETrue if successful. |
|
947 */ |
951 TBool CScsiProtocol::HandleVerify10(TPtrC8& aData, TUint aLun) |
948 TBool CScsiProtocol::HandleVerify10(TPtrC8& aData, TUint aLun) |
952 { |
949 { |
953 __FNLOG("CScsiProtocol::HandleVerify10"); |
950 OstTrace0(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_VERIFY10, ">>> VERIFY(10)"); |
954 CMassStorageDrive* drive = GetCheckDrive(aLun); |
951 CMassStorageDrive* drive = GetCheckDrive(aLun); |
955 if (drive == NULL) |
952 if (drive == NULL) |
956 { |
953 { |
957 return EFalse; |
954 return EFalse; |
958 } |
955 } |
959 |
956 |
960 TInt vrProtect = aData[2] >> 5; |
957 TInt vrProtect = aData[2] >> 5; |
961 if (vrProtect) |
958 if (vrProtect) |
962 { |
959 { |
963 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb); |
960 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb); |
964 return EFalse; |
961 return EFalse; |
965 } |
962 } |
966 |
963 |
967 const TUint32 lba = LBA(aData); |
964 const TUint32 lba = LBA(aData); |
968 const TUint16 len = LEN(aData); |
965 const TUint32 len = LEN(aData); |
969 __PRINT2(_L("VERIFY(10) : LBA = %d, Length = %d (blocks)\n"), lba, len); |
966 OstTraceExt2(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_VERIFY10_1, "VERIFY(10) : LBA = 0x%x Transfer Len = 0x%x", lba, len); |
970 |
967 |
971 TInt bytChk = aData[2] & 0x02; |
968 TInt bytChk = aData[2] & 0x02; |
972 if (!len) |
969 if (!len) |
973 { |
970 { |
974 return ETrue; // do nothing - this is not an error |
971 return ETrue; // do nothing - this is not an error |
975 } |
972 } |
976 |
973 |
977 TLocalDriveCapsV4 driveInfo; |
974 TLocalDriveCapsV4 driveInfo; |
978 TInt err = drive->Caps(driveInfo); |
975 TInt err = drive->Caps(driveInfo); |
979 if (err != KErrNone) |
976 if (err != KErrNone) |
980 { |
977 { |
981 __PRINT1(_L("Can't obtain drive Caps. Err=%d \n"), err); |
978 OstTrace1(TRACE_SMASSSTORAGE, CSCSIPROTOCOL_VERIFY10_2, "ERROR: Can't obtain drive Caps Err=%d", err); |
982 iSenseInfo.SetSense(TSenseInfo::ENotReady, TSenseInfo::EMediaNotPresent); |
979 iSenseInfo.SetSense(TSenseInfo::ENotReady, TSenseInfo::EMediaNotPresent); |
983 return EFalse; |
980 return EFalse; |
984 } |
981 } |
985 |
982 |
986 const TInt64 bOffset = MAKE_TINT64(0, lba) * KDefaultBlockSize; |
983 const TInt64 bOffset = MAKE_TINT64(0, lba) * KDefaultBlockSize; |
987 const TInt bLength = len * KDefaultBlockSize; |
984 const TInt bLength = len * KDefaultBlockSize; |
988 const TInt64 theEnd = bOffset + MAKE_TINT64(0, bLength); |
985 const TInt64 theEnd = bOffset + MAKE_TINT64(0, bLength); |
989 const TInt64 mediaSize = (driveInfo.iDriveAtt & KDriveAttLogicallyRemovable) ? driveInfo.iSize : driveInfo.MediaSizeInBytes() ; |
986 const TInt64 mediaSize = (driveInfo.iDriveAtt & KDriveAttLogicallyRemovable) ? driveInfo.iSize : driveInfo.MediaSizeInBytes() ; |
990 |
987 |
991 // check if media big enough for this request |
988 // check if media big enough for this request |
992 if (theEnd > mediaSize) |
989 if (theEnd > mediaSize) |
993 { |
990 { |
994 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::ELbaOutOfRange); |
991 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::ELbaOutOfRange); |
995 return EFalse; |
992 return EFalse; |
996 } |
993 } |
997 |
994 |
998 // check if our buffer can hold requested data |
995 // check if our buffer can hold requested data |
999 #ifdef MSDC_MULTITHREADED |
996 #ifdef MSDC_MULTITHREADED |
1000 if (iWriteDriveThread->iThreadContext->MaxBufferLength() < bLength) |
997 if (iWriteDriveThread->iThreadContext->MaxBufferLength() < bLength) |
1001 #else |
998 #else |
1002 TPtr8 writeBuf(NULL, 0); |
999 TPtr8 writeBuf(NULL, 0); |
1003 iTransport->GetReadDataBufPtr(writeBuf); |
1000 iTransport->GetReadDataBufPtr(writeBuf); |
1004 if (writeBuf.MaxLength() < bLength) |
1001 if (writeBuf.MaxLength() < bLength) |
1005 #endif |
1002 #endif |
1006 { |
1003 { |
1007 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb); |
1004 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest, TSenseInfo::EInvalidFieldInCdb); |
1008 return EFalse; |
1005 return EFalse; |
1009 } |
1006 } |
1010 |
1007 |
1011 if (!bytChk) |
1008 if (!bytChk) |
1012 { |
1009 { |
1013 // BYTCHK==0 : Perform a medium verification with no data comparison and not transfer any data from the application client data-out buffer. |
1010 // BYTCHK==0 : Perform a medium verification with no data comparison and not transfer any data from the application client data-out buffer. |
1014 // The device should attempt to read from the specified locations |
1011 // The device should attempt to read from the specified locations |
1015 #ifdef MSDC_MULTITHREADED |
1012 #ifdef MSDC_MULTITHREADED |
1016 TPtr8 writeBuf = iWriteDriveThread->iThreadContext->GetReadBuffer(bLength); |
1013 TPtr8 writeBuf = iWriteDriveThread->iThreadContext->GetReadBuffer(bLength); |
1017 #else |
1014 #else |
1018 writeBuf.SetLength(bLength); |
1015 writeBuf.SetLength(bLength); |
1019 #endif |
1016 #endif |
1020 err = drive->Read(bOffset, bLength, writeBuf, drive->IsWholeMediaAccess()); |
1017 err = drive->Read(bOffset, bLength, writeBuf, drive->IsWholeMediaAccess()); |
1021 if (err != KErrNone) |
1018 if (err != KErrNone) |
1022 { |
1019 { |
1023 iSenseInfo.SetSense(TSenseInfo::EMisCompare); |
1020 iSenseInfo.SetSense(TSenseInfo::EMisCompare); |
1024 return EFalse; |
1021 return EFalse; |
1025 } |
1022 } |
1026 return ETrue; |
1023 return ETrue; |
1027 } |
1024 } |
1028 |
1025 |
1029 // BYTCHK==1 : perform a byte-by-byte comparison of user data read from the medium & user data transferred from the application client data-out buffer. |
1026 // BYTCHK==1 : perform a byte-by-byte comparison of user data read from the medium & user data transferred from the application client data-out buffer. |
1030 // The host sends data in the data-transport phase, and the device should verify that the received data matches what is stored in the device. |
1027 // The host sends data in the data-transport phase, and the device should verify that the received data matches what is stored in the device. |
1031 |
1028 |
1032 iOffset = bOffset; |
1029 iOffset = bOffset; |
1033 iLastCommand = EVerify10; |
1030 iLastCommand = EVerify10; |
1034 iLastLun = aLun; |
1031 iLastLun = aLun; |
1035 |
1032 |
1036 iTransport->SetupReadData(bLength); |
1033 iTransport->SetupReadData(bLength); |
1037 |
1034 |
1038 return ETrue; |
1035 return ETrue; |
1039 } |
1036 } |
1040 |
1037 |
1041 |
1038 |
1042 /** |
1039 /** |
1043 Called by the transport when the requested data has been read or an error has |
1040 Called by the transport when the requested data has been read or an error has |
1044 occurred during the read. |
1041 occurred during the read. |
1049 the transfer immediately, KErrNotReady if insufficient data is |
1046 the transfer immediately, KErrNotReady if insufficient data is |
1050 available in the buffer so the transport should wait for it to arrive, |
1047 available in the buffer so the transport should wait for it to arrive, |
1051 KErrNone if command processing is complete and was successful. |
1048 KErrNone if command processing is complete and was successful. |
1052 */ |
1049 */ |
1053 TInt CScsiProtocol::ReadComplete(TInt aError) |
1050 TInt CScsiProtocol::ReadComplete(TInt aError) |
1054 { |
1051 { |
1055 __FNLOG("CScsiProtocol::ReadComplete"); |
1052 OstTrace1(TRACE_SMASSSTORAGE_MEDIA, CSCSIPROTOCOL_READCOMPLETE0, "ReadComplete = 0x%X", aError); |
1056 __PRINT1(_L("Error = 0x%X \n"), aError); |
1053 const TInt64 bOffset = iOffset; |
1057 const TInt64 bOffset = iOffset; |
1054 TUint8 lastCommand = iLastCommand; |
1058 TUint8 lastCommand = iLastCommand; |
1055 TUint lastLun = iLastLun; |
1059 TUint lastLun = iLastLun; |
1056 |
1060 |
1057 iOffset = 0; |
1061 iOffset = 0; |
1058 iLastCommand = EUndefinedCommand; |
1062 iLastCommand = EUndefinedCommand; |
1059 iLastLun = KUndefinedLun; |
1063 iLastLun = KUndefinedLun; |
1060 |
1064 |
1061 // OstTrace1(TRACE_SMASSSTORAGE_MEDIA, CSCSIPROTOCOL_READCOMPLETE1, "lastCommand = d", lastCommand); |
1065 __PRINT1(_L("Last command was: %s\n"), |
1062 |
1066 (lastCommand == EUndefinedCommand) ? _S("Undefined") : |
1063 if (aError != KErrNone || |
1067 ((lastCommand == EWrite10) ? _S("EWrite10") : |
1064 lastCommand == EUndefinedCommand || |
1068 ((lastCommand == EVerify10) ? _S("EVerify10") : |
1065 lastLun == KUndefinedLun) |
1069 _S("Unknown")))); |
1066 { |
1070 |
1067 iSenseInfo.SetSense(TSenseInfo::EAbortedCommand); |
1071 if (aError != KErrNone || |
1068 return KErrAbort; |
1072 lastCommand == EUndefinedCommand || |
1069 } |
1073 lastLun == KUndefinedLun) |
1070 |
1074 { |
1071 CMassStorageDrive* drive = GetCheckDrive(lastLun); |
1075 iSenseInfo.SetSense(TSenseInfo::EAbortedCommand); |
1072 if (drive == NULL) |
1076 return KErrAbort; |
1073 { |
1077 } |
1074 return KErrAbort; |
1078 |
1075 } |
1079 CMassStorageDrive* drive = GetCheckDrive(lastLun); |
1076 |
1080 if (drive == NULL) |
1077 if (lastCommand == EWrite10) |
1081 { |
1078 { |
1082 return KErrAbort; |
1079 TPtrC8 writeBuf(NULL, 0); |
1083 } |
1080 iTransport->GetWriteDataBufPtr(writeBuf); |
1084 |
1081 |
1085 if (lastCommand == EWrite10) |
|
1086 { |
|
1087 TPtrC8 writeBuf(NULL, 0); |
|
1088 iTransport->GetWriteDataBufPtr(writeBuf); |
|
1089 |
|
1090 #ifdef USB_TRANSFER_PUBLISHER |
1082 #ifdef USB_TRANSFER_PUBLISHER |
1091 iBytesWritten[lastLun] += writeBuf.Length(); |
1083 iBytesWritten[lastLun] += writeBuf.Length(); |
1092 #endif |
1084 #endif |
1093 |
1085 |
1094 #ifdef MSDC_MULTITHREADED |
1086 #ifdef MSDC_MULTITHREADED |
1095 TInt err = iWriteDriveThread->WriteDriveData(drive, bOffset, writeBuf, ProcessWriteComplete, this); |
1087 TInt err = iWriteDriveThread->WriteDriveData(drive, bOffset, writeBuf, ProcessWriteComplete, this); |
1096 |
1088 |
1097 if (err != KErrNone) |
1089 if (err != KErrNone) |
1098 { |
1090 { |
1099 iDeferredSenseInfo.SetSense(TSenseInfo::EMediumError); |
1091 iDeferredSenseInfo.SetSense(TSenseInfo::EMediumError); |
1100 } |
1092 } |
1101 |
1093 |
1102 TUint thisLength = iWriteDriveThread->WriteBufferLength(); |
1094 TUint thisLength = iWriteDriveThread->WriteBufferLength(); |
1103 #else |
1095 #else |
1104 #ifdef MEASURE_AND_DISPLAY_WRITE_TIME |
1096 OstTrace1(TRACE_SMASSSTORAGE_MEDIA, CSCSIPROTOCOL_READCOMPLETE2, "SCSI: writing 0x%x bytes", writeBuf.Length()); |
1105 RDebug::Print(_L("SCSI: writing %d bytes\n"), writeBuf.Length()); |
1097 TInt err = drive->Write(bOffset, writeBuf, drive->IsWholeMediaAccess()); |
1106 TTime t0, t1; |
1098 if (err != KErrNone) |
1107 t0.HomeTime(); |
1099 { |
|
1100 OstTrace1(TRACE_SMASSSTORAGE_MEDIA, CSCSIPROTOCOL_READCOMPLETE3, "Error after write = 0x%x", err); |
|
1101 iSenseInfo.SetSense(TSenseInfo::EAbortedCommand); |
|
1102 return KErrAbort; |
|
1103 } |
|
1104 |
|
1105 TUint thisLength = writeBuf.Length(); |
|
1106 #endif // MSDC_MULTITHREADED |
|
1107 iOffset = bOffset + MAKE_TINT64(0, thisLength); |
|
1108 iBytesRemain -= thisLength; |
|
1109 if ((TInt)iBytesRemain > 0) |
|
1110 { |
|
1111 // More data is expected - set up another request to read from the host |
|
1112 iLastCommand = EWrite10; |
|
1113 iLastLun = lastLun; |
|
1114 |
|
1115 TUint minLength = (iBytesRemain < iMediaWriteSize) ? iBytesRemain : iMediaWriteSize; |
|
1116 TUint bytesAvail = iTransport->BytesAvailable() & ~(KDefaultBlockSize-1); |
|
1117 |
|
1118 TBool wait = EFalse; |
|
1119 thisLength = bytesAvail ? bytesAvail : minLength; |
|
1120 if (thisLength < minLength) |
|
1121 { |
|
1122 // Not enough data is available at the transport to satisfy the request, |
|
1123 // so return KErrNotReady to indicate that the transport should wait. |
|
1124 thisLength = minLength; |
|
1125 wait = ETrue; |
|
1126 } |
|
1127 |
|
1128 thisLength = (thisLength > KMaxBufSize) ? KMaxBufSize : thisLength; |
|
1129 |
|
1130 iTransport->SetupReadData(thisLength); |
|
1131 |
|
1132 return wait ? KErrNotReady : KErrCompletion; |
|
1133 } |
|
1134 } |
|
1135 else if (lastCommand == EVerify10) |
|
1136 { |
|
1137 HBufC8* hostData = NULL; |
|
1138 TPtrC8 writeBuf(NULL, 0); |
|
1139 iTransport->GetWriteDataBufPtr(writeBuf); |
|
1140 #ifdef MSDC_MULTITHREADED |
|
1141 TRAPD(err, hostData = HBufC8::NewL(writeBuf.Length())); |
1108 #else |
1142 #else |
1109 __PRINT1(_L("SCSI: writing %d bytes\n"), writeBuf.Length()); |
1143 TRAPD(err, hostData = HBufC8::NewL(writeBuf.Length())); |
1110 #endif |
1144 #endif |
1111 |
1145 if (err != KErrNone || hostData == NULL) |
1112 #ifdef INJECT_ERROR |
1146 { |
1113 if (writeBuf[0] == '2') |
1147 iSenseInfo.SetSense(TSenseInfo::EAbortedCommand, TSenseInfo::EInsufficientRes); |
1114 { |
1148 return KErrAbort; |
1115 writeBuf[0] = 'x'; |
1149 } |
1116 RDebug::Printf("Injecting error"); |
1150 |
1117 } |
1151 #ifdef MSDC_MULTITHREADED |
1118 |
1152 // copy the data |
1119 RDebug::Printf("%08lx %x [%x] [%x]", bOffset,writeBuf.Length(), |
1153 *hostData = writeBuf; |
1120 writeBuf[0], |
1154 TPtr8 readBuf = iWriteDriveThread->iThreadContext->GetReadBuffer(); |
1121 writeBuf[writeBuf.Length()-1]); |
1155 err = drive->Read(bOffset, writeBuf.Length(), readBuf, drive->IsWholeMediaAccess()); |
1122 #endif |
1156 if (err == KErrNone) |
1123 |
1157 { |
1124 TInt err = drive->Write(bOffset, writeBuf, drive->IsWholeMediaAccess()); |
1158 err = (hostData->Compare(readBuf) == 0) ? KErrNone : KErrCorrupt; |
1125 |
1159 } |
1126 #ifdef INJECT_ERROR |
|
1127 if (writeBuf[0] == 'x') |
|
1128 { |
|
1129 err = KErrUnknown; |
|
1130 } |
|
1131 #endif |
|
1132 |
|
1133 #ifdef MEASURE_AND_DISPLAY_WRITE_TIME |
|
1134 t1.HomeTime(); |
|
1135 const TTimeIntervalMicroSeconds time = t1.MicroSecondsFrom(t0); |
|
1136 const TUint time_ms = I64LOW(time.Int64() / 1000); |
|
1137 RDebug::Print(_L("SCSI: write took %d ms\n"), time_ms); |
|
1138 #endif |
|
1139 if (err != KErrNone) |
|
1140 { |
|
1141 __PRINT1(_L("Error after write = 0x%X \n"), err); |
|
1142 iSenseInfo.SetSense(TSenseInfo::EAbortedCommand); |
|
1143 return KErrAbort; |
|
1144 } |
|
1145 |
|
1146 TUint thisLength = writeBuf.Length(); |
|
1147 #endif // MSDC_MULTITHREADED |
|
1148 iOffset = bOffset + MAKE_TINT64(0, thisLength); |
|
1149 iBytesRemain -= thisLength; |
|
1150 if ((TInt)iBytesRemain > 0) |
|
1151 { |
|
1152 // More data is expected - set up another request to read from the host |
|
1153 iLastCommand = EWrite10; |
|
1154 iLastLun = lastLun; |
|
1155 |
|
1156 TUint minLength = (iBytesRemain < iMediaWriteSize) ? iBytesRemain : iMediaWriteSize; |
|
1157 TUint bytesAvail = iTransport->BytesAvailable() & ~(KDefaultBlockSize-1); |
|
1158 |
|
1159 TBool wait = EFalse; |
|
1160 thisLength = bytesAvail ? bytesAvail : minLength; |
|
1161 if (thisLength < minLength) |
|
1162 { |
|
1163 // Not enough data is available at the transport to satisfy the request, |
|
1164 // so return KErrNotReady to indicate that the transport should wait. |
|
1165 thisLength = minLength; |
|
1166 wait = ETrue; |
|
1167 } |
|
1168 |
|
1169 thisLength = (thisLength > KMaxBufSize) ? KMaxBufSize : thisLength; |
|
1170 |
|
1171 iTransport->SetupReadData(thisLength); |
|
1172 |
|
1173 return wait ? KErrNotReady : KErrCompletion; |
|
1174 } |
|
1175 } |
|
1176 else if (lastCommand == EVerify10) |
|
1177 { |
|
1178 HBufC8* hostData = NULL; |
|
1179 TPtrC8 writeBuf(NULL, 0); |
|
1180 iTransport->GetWriteDataBufPtr(writeBuf); |
|
1181 #ifdef MSDC_MULTITHREADED |
|
1182 TRAPD(err, hostData = HBufC8::NewL(writeBuf.Length())); |
|
1183 #else |
1160 #else |
1184 TRAPD(err, hostData = HBufC8::NewL(writeBuf.Length())); |
1161 *hostData = writeBuf; |
1185 #endif |
1162 TPtr8 readBuf((TUint8*) writeBuf.Ptr(), writeBuf.Length()); |
1186 if (err != KErrNone || hostData == NULL) |
1163 err = drive->Read(bOffset, writeBuf.Length(), readBuf, drive->IsWholeMediaAccess()); |
1187 { |
1164 if (err == KErrNone) |
1188 iSenseInfo.SetSense(TSenseInfo::EAbortedCommand, TSenseInfo::EInsufficientRes); |
1165 { |
1189 return KErrAbort; |
1166 err = (hostData->Compare(readBuf) == 0) ? KErrNone : KErrCorrupt; |
1190 } |
1167 } |
1191 |
1168 #endif |
1192 #ifdef MSDC_MULTITHREADED |
1169 |
1193 // copy the data |
1170 if (err != KErrNone) |
1194 *hostData = writeBuf; |
1171 { |
1195 TPtr8 readBuf = iWriteDriveThread->iThreadContext->GetReadBuffer(); |
1172 iSenseInfo.SetSense(TSenseInfo::EMisCompare); |
1196 err = drive->Read(bOffset, writeBuf.Length(), readBuf, drive->IsWholeMediaAccess()); |
1173 } |
1197 if (err == KErrNone) |
1174 |
1198 { |
1175 delete hostData; |
1199 err = (hostData->Compare(readBuf) == 0) ? KErrNone : KErrCorrupt; |
1176 } |
1200 } |
1177 else // unknown command |
1201 #else |
1178 { |
1202 *hostData = writeBuf; |
1179 iSenseInfo.SetSense(TSenseInfo::EAbortedCommand); |
1203 TPtr8 readBuf((TUint8*) writeBuf.Ptr(), writeBuf.Length()); |
1180 } |
1204 err = drive->Read(bOffset, writeBuf.Length(), readBuf, drive->IsWholeMediaAccess()); |
1181 return iSenseInfo.SenseOk() ? KErrNone : KErrAbort; |
1205 if (err == KErrNone) |
1182 } |
1206 { |
|
1207 err = (hostData->Compare(readBuf) == 0) ? KErrNone : KErrCorrupt; |
|
1208 } |
|
1209 #endif |
|
1210 |
|
1211 if (err != KErrNone) |
|
1212 { |
|
1213 iSenseInfo.SetSense(TSenseInfo::EMisCompare); |
|
1214 } |
|
1215 |
|
1216 delete hostData; |
|
1217 } |
|
1218 else // unknown command |
|
1219 { |
|
1220 iSenseInfo.SetSense(TSenseInfo::EAbortedCommand); |
|
1221 } |
|
1222 return iSenseInfo.SenseOk() ? KErrNone : KErrAbort; |
|
1223 } |
|
1224 |
1183 |
1225 |
1184 |
1226 /** |
1185 /** |
1227 Command Parser for the MODE SENSE(06) command (0x1A) |
1186 Command Parser for the MODE SENSE(06) command (0x1A) |
1228 |
1187 |
1229 @return ETrue if successful. |
1188 @return ETrue if successful. |
1230 */ |
1189 */ |
1231 TBool CScsiProtocol::HandleModeSense6(TPtrC8& aData, TUint aLun) |
1190 TBool CScsiProtocol::HandleModeSense6(TPtrC8& aData, TUint aLun) |
1232 { |
1191 { |
1233 __FNLOG("CScsiProtocol::HandleModeSense6"); |
1192 OstTrace0(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_MODESENSE6, ">>> MODESENSE(06)"); |
1234 |
1193 TInt pageCode = aData[3] & 0x3F; |
1235 TInt pageCode = aData[3] & 0x3F; |
1194 TUint8 pageControl= static_cast<TUint8>(aData[3] >>6); |
1236 TUint8 pageControl= static_cast<TUint8>(aData[3] >>6); |
1195 |
1237 |
1196 if (pageCode != KAllPages || pageControl == KChangeableValues) |
1238 if (pageCode != KAllPages || pageControl == KChangeableValues) |
1197 { |
1239 { |
1198 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest,TSenseInfo::EInvalidFieldInCdb); |
1240 __PRINT(_L("TSenseInfo::EIllegalRequest,TSenseInfo::EInvalidFieldInCdb")); |
1199 return EFalse; |
1241 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest,TSenseInfo::EInvalidFieldInCdb); |
1200 } |
1242 return EFalse; |
1201 |
1243 } |
1202 // reserve 4 bytes for Length, Media type, Device-specific parameter and Block descriptor length |
1244 |
1203 TPtr8 writeBuf(NULL, 0); |
1245 // reserve 4 bytes for Length, Media type, Device-specific parameter and Block descriptor length |
1204 iTransport->GetCommandBufPtr(writeBuf, KModeSense6CommandLength); |
1246 TPtr8 writeBuf(NULL, 0); |
1205 writeBuf.FillZ(KModeSense6CommandLength); |
1247 iTransport->GetCommandBufPtr(writeBuf, KModeSense6CommandLength); |
1206 |
1248 writeBuf.FillZ(KModeSense6CommandLength); |
1207 if (pageControl != KDefaultValues) |
1249 |
1208 { |
1250 if (pageControl != KDefaultValues) |
1209 //check if drive write protected |
1251 { |
1210 CMassStorageDrive* drive=GetCheckDrive(aLun); |
1252 //check if drive write protected |
1211 if (drive == NULL) |
1253 CMassStorageDrive* drive=GetCheckDrive(aLun); |
1212 { |
1254 if (drive == NULL) |
1213 OstTrace0(TRACE_SMASSSTORAGE, CSCSIPROTOCOL_HANDLEMODESENSE6_1, "drive == null"); |
1255 { |
1214 return EFalse; |
1256 __PRINT(_L("drive == null")); |
1215 } |
1257 return EFalse; |
1216 |
1258 } |
1217 TLocalDriveCapsV4 driveInfo; |
1259 |
1218 TInt err = drive->Caps(driveInfo); |
1260 TLocalDriveCapsV4 driveInfo; |
1219 if (err != KErrNone) |
1261 TInt err = drive->Caps(driveInfo); |
1220 { |
1262 if (err != KErrNone) |
1221 OstTrace1(TRACE_SMASSSTORAGE, CSCSIPROTOCOL_MODESENSE6_2, "ERROR: Can't obtain drive Caps Err=%d", err); |
1263 { |
1222 iSenseInfo.SetSense(TSenseInfo::ENotReady, TSenseInfo::EMediaNotPresent); |
1264 __PRINT(_L("TSenseInfo::ENotReady")); |
1223 return EFalse ; |
1265 iSenseInfo.SetSense(TSenseInfo::ENotReady, TSenseInfo::EMediaNotPresent); |
1224 } |
1266 return EFalse ; |
1225 |
1267 } |
1226 if (driveInfo.iMediaAtt & KMediaAttWriteProtected) |
1268 |
1227 { |
1269 if (driveInfo.iMediaAtt & KMediaAttWriteProtected) |
1228 writeBuf[2] = 1<<7; // set SWP bit at the Device Specific parameters |
1270 { |
1229 } |
1271 writeBuf[2] = 1<<7; // set SWP bit at the Device Specific parameters |
1230 } |
1272 } |
1231 |
1273 } |
1232 writeBuf[0]=3; //Sending only Mode parameter header |
1274 |
1233 |
1275 writeBuf[0]=3; //Sending only Mode parameter header |
1234 TPtrC8 writeBuf1 = writeBuf; |
1276 |
1235 |
1277 TPtrC8 writeBuf1 = writeBuf; |
1236 iTransport->SetupWriteData(writeBuf1); |
1278 |
1237 |
1279 iTransport->SetupWriteData(writeBuf1); |
1238 return (iSenseInfo.SenseOk()); |
1280 |
1239 } |
1281 return (iSenseInfo.SenseOk()); |
|
1282 } |
|
1283 |
1240 |
1284 |
1241 |
1285 /** |
1242 /** |
1286 Command Parser for the MODE SENSE(10) command (0x5A) |
1243 Command Parser for the MODE SENSE(10) command (0x5A) |
1287 |
1244 |
1288 @return ETrue if successful. |
1245 @return ETrue if successful. |
1289 */ |
1246 */ |
1290 TBool CScsiProtocol::HandleModeSense10(TPtrC8& aData, TUint aLun) |
1247 TBool CScsiProtocol::HandleModeSense10(TPtrC8& aData, TUint aLun) |
1291 { |
1248 { |
1292 __FNLOG("CScsiProtocol::HandleModeSense10"); |
1249 OstTrace0(TRACE_SMASSSTORAGE_SCSI, CSCSIPROTOCOL_MODESENSE10, ">>> MODESENSE(10)"); |
1293 |
1250 TInt pageCode = aData[3] & 0x3F; |
1294 TInt pageCode = aData[3] & 0x3F; |
1251 TUint8 pageControl= static_cast<TUint8>(aData[3] >>6); |
1295 TUint8 pageControl= static_cast<TUint8>(aData[3] >>6); |
1252 |
1296 |
1253 if (pageCode != KAllPages || pageControl == KChangeableValues) |
1297 if (pageCode != KAllPages || pageControl == KChangeableValues) |
1254 { |
1298 { |
1255 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest,TSenseInfo::EInvalidFieldInCdb); |
1299 __PRINT(_L("TSenseInfo::EIllegalRequest,TSenseInfo::EInvalidFieldInCdb")); |
1256 return EFalse; |
1300 iSenseInfo.SetSense(TSenseInfo::EIllegalRequest,TSenseInfo::EInvalidFieldInCdb); |
1257 } |
1301 return EFalse; |
1258 |
1302 } |
1259 // reserve 8 bytes for Length, Media type, Device-specific parameter and Block descriptor length |
1303 |
1260 TPtr8 writeBuf(NULL, 0); |
1304 // reserve 8 bytes for Length, Media type, Device-specific parameter and Block descriptor length |
1261 iTransport->GetCommandBufPtr(writeBuf, KModeSense10CommandLength); |
1305 TPtr8 writeBuf(NULL, 0); |
1262 writeBuf.FillZ(KModeSense10CommandLength); |
1306 iTransport->GetCommandBufPtr(writeBuf, KModeSense10CommandLength); |
1263 |
1307 writeBuf.FillZ(KModeSense10CommandLength); |
1264 if (pageControl != KDefaultValues) |
1308 |
1265 { |
1309 if (pageControl != KDefaultValues) |
1266 //check if drive write protected |
1310 { |
1267 CMassStorageDrive* drive=GetCheckDrive(aLun); |
1311 //check if drive write protected |
1268 if (drive == NULL) |
1312 CMassStorageDrive* drive=GetCheckDrive(aLun); |
1269 { |
1313 if (drive == NULL) |
1270 OstTrace0(TRACE_SMASSSTORAGE, CSCSIPROTOCOL_HANDLEMODESENSE10_1, "drive == null"); |
1314 { |
1271 return EFalse; |
1315 __PRINT(_L("drive == null")); |
1272 } |
1316 return EFalse; |
1273 |
1317 } |
1274 TLocalDriveCapsV4 driveInfo; |
1318 |
1275 TInt err = drive->Caps(driveInfo); |
1319 TLocalDriveCapsV4 driveInfo; |
1276 if (err != KErrNone) |
1320 TInt err = drive->Caps(driveInfo); |
1277 { |
1321 if (err != KErrNone) |
1278 OstTrace1(TRACE_SMASSSTORAGE, CSCSIPROTOCOL_MODESENSE10_1, "ERROR: Can't obtain drive Caps Err=%d", err); |
1322 { |
1279 iSenseInfo.SetSense(TSenseInfo::ENotReady, TSenseInfo::EMediaNotPresent); |
1323 __PRINT(_L("TSenseInfo::ENotReady")); |
1280 return EFalse ; |
1324 iSenseInfo.SetSense(TSenseInfo::ENotReady, TSenseInfo::EMediaNotPresent); |
1281 } |
1325 return EFalse ; |
1282 |
1326 } |
1283 if (driveInfo.iMediaAtt & KMediaAttWriteProtected) |
1327 |
1284 { |
1328 if (driveInfo.iMediaAtt & KMediaAttWriteProtected) |
1285 writeBuf[3] = 1<<7; // set SWP bit at the Device Specific parameters |
1329 { |
1286 } |
1330 writeBuf[3] = 1<<7; // set SWP bit at the Device Specific parameters |
1287 } |
1331 } |
1288 |
1332 } |
1289 writeBuf[1]=6; //Sending only Mode parameter header |
1333 |
1290 |
1334 writeBuf[1]=6; //Sending only Mode parameter header |
1291 TPtrC8 writeBuf1 = writeBuf; |
1335 |
1292 |
1336 TPtrC8 writeBuf1 = writeBuf; |
1293 iTransport->SetupWriteData(writeBuf1); |
1337 |
1294 |
1338 iTransport->SetupWriteData(writeBuf1); |
1295 return (iSenseInfo.SenseOk()); |
1339 |
1296 } |
1340 return (iSenseInfo.SenseOk()); |
1297 |
1341 } |
1298 |
1342 |
1299 |
1343 |
|
1344 |
|