bool CmtUsbMsc::Init() { uint8 capasity[36]; //Первый этап-чтение INQURY memset( &mCbw, 0, sizeof(MSC_CBW) ); mCbw.bCBLength = 6; mCbw.CB[0] = SCSI_INQUIRY; mCbw.CB[4] = 36; if( ReadSCSI( capasity, 36 ) != CMTE_OK ) return false; //Второй этап-чтение SENCE if( !RequestSense( capasity ) ) return false; //READ_FORMAT_CAPASITY memset( &mCbw, 0, sizeof(MSC_CBW) ); mCbw.bCBLength = 10; mCbw.CB[0] = SCSI_READ_FORMAT_CAPACITIES; mCbw.CB[8] = 12; if( ReadSCSI( capasity, 12 ) != CMTE_OK ) { //Для такого дебильного Flash подать SCSI_REQUEST_SENSE if( !RequestSense( capasity ) ) return false; //Повторить CAPASITY memset( &mCbw, 0, sizeof(MSC_CBW) ); mCbw.bCBLength = 10; mCbw.CB[0] = SCSI_READ_FORMAT_CAPACITIES; mCbw.CB[8] = 12; if( ReadSCSI( capasity, 12 ) != CMTE_OK ) return false; //Повторный CAPASITY провалился } if( capasity[8] == 2 ) { mBlockSize = capasity[11] | (capasity[10] << 8) | (capasity[9] << 16); mBlockCount = capasity[7] | (capasity[6] << 8) | (capasity[5] << 16) | (capasity[4] << 24); } else { //Воспользуемся другой командой //CAPASITY memset( &mCbw, 0, sizeof(MSC_CBW) ); mCbw.bCBLength = 8; mCbw.CB[0] = SCSI_READ_CAPACITY; if( ReadSCSI( capasity, 8 ) != CMTE_OK ) { //Для такого дебильного Flash подать SCSI_REQUEST_SENSE if( !RequestSense( capasity ) ) return false; //И Sense не помог memset( &mCbw, 0, sizeof(MSC_CBW) ); mCbw.bCBLength = 8; mCbw.CB[0] = SCSI_READ_CAPACITY; if( ReadSCSI( capasity, 8 ) != CMTE_OK ) return false; //Повторный CAPASITY провалился } mBlockSize = capasity[7] | (capasity[6] << 8) | (capasity[5] << 16); mBlockCount = capasity[3] | (capasity[2] << 8) | (capasity[1] << 16) | (capasity[0] << 24); } //Инициализация прошла успешно return true; }
/** * For driver use only. * * @param status * @return */ uint8_t BulkOnly::HandleSCSIError(uint8_t status) { uint8_t ret = 0; switch(status) { case 0: return MASS_ERR_SUCCESS; case 2: ErrorMessage<uint8_t > (PSTR("Phase Error"), status); ErrorMessage<uint8_t > (PSTR("LUN"), bTheLUN); ResetRecovery(); return MASS_ERR_GENERAL_SCSI_ERROR; case 1: ErrorMessage<uint8_t > (PSTR("SCSI Error"), status); ErrorMessage<uint8_t > (PSTR("LUN"), bTheLUN); RequestSenseResponce rsp; ret = RequestSense(bTheLUN, sizeof (RequestSenseResponce), (uint8_t*) & rsp); if(ret) { return MASS_ERR_GENERAL_SCSI_ERROR; } ErrorMessage<uint8_t > (PSTR("Response Code"), rsp.bResponseCode); if(rsp.bResponseCode & 0x80) { Notify(PSTR("Information field: "), 0x80); for(int i = 0; i < 4; i++) { D_PrintHex<uint8_t > (rsp.CmdSpecificInformation[i], 0x80); Notify(PSTR(" "), 0x80); } Notify(PSTR("\r\n"), 0x80); } ErrorMessage<uint8_t > (PSTR("Sense Key"), rsp.bmSenseKey); ErrorMessage<uint8_t > (PSTR("Add Sense Code"), rsp.bAdditionalSenseCode); ErrorMessage<uint8_t > (PSTR("Add Sense Qual"), rsp.bAdditionalSenseQualifier); // warning, this is not testing ASQ, only SK and ASC. switch(rsp.bmSenseKey) { case SCSI_S_UNIT_ATTENTION: switch(rsp.bAdditionalSenseCode) { case SCSI_ASC_MEDIA_CHANGED: return MASS_ERR_MEDIA_CHANGED; default: return MASS_ERR_UNIT_NOT_READY; } case SCSI_S_NOT_READY: switch(rsp.bAdditionalSenseCode) { case SCSI_ASC_MEDIUM_NOT_PRESENT: return MASS_ERR_NO_MEDIA; default: return MASS_ERR_UNIT_NOT_READY; } case SCSI_S_ILLEGAL_REQUEST: switch(rsp.bAdditionalSenseCode) { case SCSI_ASC_LBA_OUT_OF_RANGE: return MASS_ERR_BAD_LBA; default: return MASS_ERR_CMD_NOT_SUPPORTED; } default: return MASS_ERR_GENERAL_SCSI_ERROR; } // case 4: return MASS_ERR_UNIT_BUSY; // Busy means retry later. // case 0x05/0x14: we stalled out // case 0x15/0x16: we naked out. default: ErrorMessage<uint8_t > (PSTR("Gen SCSI Err"), status); ErrorMessage<uint8_t > (PSTR("LUN"), bTheLUN); return status; } // switch }