/******************************************************************************* * Function Name : SCSI_Invalid_Cmd * Description : Invalid Commands routine * Input : None. * Output : None. * Return : None. *******************************************************************************/ void SCSI_Invalid_Cmd(uint8_t lun) { if (CBW.dDataLength == 0) { Bot_Abort(DIR_IN); } else { if ((CBW.bmFlags & 0x80) != 0) { Bot_Abort(DIR_IN); } else { Bot_Abort(BOTH_DIR); } } Set_Scsi_Sense_Data(CBW.bLUN, ILLEGAL_REQUEST, INVALID_COMMAND); Set_CSW (CSW_CMD_FAILED, SEND_CSW_DISABLE); }
/******************************************************************************* * Function Name : SCSI_ReadFormatCapacity_Cmd * Description : SCSI ReadFormatCapacity Command routine. * Input : None. * Output : None. * Return : None. *******************************************************************************/ void SCSI_ReadFormatCapacity_Cmd(uint8_t lun) { if (MAL_GetStatus(lun) != 0 ) { Set_Scsi_Sense_Data(CBW.bLUN, NOT_READY, MEDIUM_NOT_PRESENT); Set_CSW (CSW_CMD_FAILED, SEND_CSW_ENABLE); Bot_Abort(DIR_IN); return; } ReadFormatCapacity_Data[4] = (uint8_t)(Mass_Block_Count[lun] >> 24); ReadFormatCapacity_Data[5] = (uint8_t)(Mass_Block_Count[lun] >> 16); ReadFormatCapacity_Data[6] = (uint8_t)(Mass_Block_Count[lun] >> 8); ReadFormatCapacity_Data[7] = (uint8_t)(Mass_Block_Count[lun]); ReadFormatCapacity_Data[9] = (uint8_t)(Mass_Block_Size[lun] >> 16); ReadFormatCapacity_Data[10] = (uint8_t)(Mass_Block_Size[lun] >> 8); ReadFormatCapacity_Data[11] = (uint8_t)(Mass_Block_Size[lun]); Transfer_Data_Request(ReadFormatCapacity_Data, READ_FORMAT_CAPACITY_DATA_LEN); }
/******************************************************************************* * Function Name : Mass_Storage_In * Description : Mass Storage IN transfer. * Input : None. * Output : None. * Return : None. *******************************************************************************/ void Mass_Storage_In (void) { switch (Bot_State) { case BOT_CSW_Send: case BOT_ERROR: Bot_State = BOT_IDLE; #ifndef STM32F10X_CL SetEPRxStatus(ENDP2, EP_RX_VALID);/* enable the Endpoint to receive the next cmd*/ #else if (GetEPRxStatus(EP2_OUT) == EP_RX_STALL) { SetEPRxStatus(EP2_OUT, EP_RX_VALID);/* enable the Endpoint to receive the next cmd*/ } #endif /* STM32F10X_CL */ break; case BOT_DATA_IN: switch (CBW.CB[0]) { case SCSI_READ10: //DBG("SCSI_READ10\n"); SCSI_Read10_Cmd(CBW.bLUN , SCSI_LBA , SCSI_BlkLen); break; } break; case BOT_DATA_IN_LAST: Set_CSW (CSW_CMD_PASSED, SEND_CSW_ENABLE); #ifndef STM32F10X_CL SetEPRxStatus(ENDP2, EP_RX_VALID); #else if (GetEPRxStatus(EP2_OUT) == EP_RX_STALL) { SetEPRxStatus(EP2_OUT, EP_RX_VALID);/* enable the Endpoint to receive the next cmd*/ } #endif /* STM32F10X_CL */ break; default: break; } }
/******************************************************************************* * Function Name : SCSI_ReadCapacity10_Cmd * Description : SCSI ReadCapacity10 Command routine. * Input : None. * Output : None. * Return : None. *******************************************************************************/ void SCSI_ReadCapacity10_Cmd(u8 lun) { if (MAL_GetStatus(lun)) { Set_Scsi_Sense_Data(CBW.bLUN, NOT_READY, MEDIUM_NOT_PRESENT); Set_CSW (CSW_CMD_FAILED, SEND_CSW_ENABLE); Bot_Abort(DIR_IN); return; } ReadCapacity10_Data[0] = (u8)(Mass_Block_Count[lun] - 1 >> 24); ReadCapacity10_Data[1] = (u8)(Mass_Block_Count[lun] - 1 >> 16); ReadCapacity10_Data[2] = (u8)(Mass_Block_Count[lun] - 1 >> 8); ReadCapacity10_Data[3] = (u8)(Mass_Block_Count[lun] - 1); ReadCapacity10_Data[4] = (u8)(Mass_Block_Size[lun] >> 24); ReadCapacity10_Data[5] = (u8)(Mass_Block_Size[lun] >> 16); ReadCapacity10_Data[6] = (u8)(Mass_Block_Size[lun] >> 8); ReadCapacity10_Data[7] = (u8)(Mass_Block_Size[lun]); Transfer_Data_Request(ReadCapacity10_Data, READ_CAPACITY10_DATA_LEN); }
/******************************************************************************* * Function Name : SCSI_ReadCapacity10_Cmd * Description : SCSI ReadCapacity10 Command routine. * Input : None. * Output : None. * Return : None. *******************************************************************************/ void SCSI_ReadCapacity10_Cmd(uint8_t lun) { if (DRV_MSp_UpdateStatus(lun)) { Set_Scsi_Sense_Data(CBW.bLUN, NOT_READY, MEDIUM_NOT_PRESENT); Set_CSW (CSW_CMD_FAILED, SEND_CSW_ENABLE); Bot_Abort(DIR_IN); return; } ReadCapacity10_Data[0] = (uint8_t)((DRV_MS_MemDevice[lun].Block_Count - 1) >> 24); ReadCapacity10_Data[1] = (uint8_t)((DRV_MS_MemDevice[lun].Block_Count - 1) >> 16); ReadCapacity10_Data[2] = (uint8_t)((DRV_MS_MemDevice[lun].Block_Count - 1) >> 8); ReadCapacity10_Data[3] = (uint8_t)(DRV_MS_MemDevice[lun].Block_Count - 1); ReadCapacity10_Data[4] = (uint8_t)(DRV_MS_MemDevice[lun].Block_Size >> 24); ReadCapacity10_Data[5] = (uint8_t)(DRV_MS_MemDevice[lun].Block_Size >> 16); ReadCapacity10_Data[6] = (uint8_t)(DRV_MS_MemDevice[lun].Block_Size >> 8); ReadCapacity10_Data[7] = (uint8_t)(DRV_MS_MemDevice[lun].Block_Size); Transfer_Data_Request(ReadCapacity10_Data, READ_CAPACITY10_DATA_LEN); }
/******************************************************************************* * Function Name : Write_Memory * Description : Handle the Write operation to the microSD card. * Input : None. * Output : None. * Return : None. *******************************************************************************/ void Write_Memory(uint8_t lun, uint32_t Memory_Offset, uint32_t Transfer_Length) { static uint32_t W_Offset, W_Length; uint32_t temp = Block_Write_count + BULK_MAX_PACKET_SIZE; uint32_t idx; if (TransferState == TXFR_IDLE) { W_Offset = Memory_Offset * Mass_Block_Size[lun]; W_Length = Transfer_Length * Mass_Block_Size[lun]; TransferState = TXFR_ONGOING; } if (TransferState == TXFR_ONGOING) { for (idx = 0 ; Block_Write_count < temp; Block_Write_count++) { *((uint8_t *)Data_Buffer + Block_Write_count) = Bulk_Data_Buff[idx++]; } W_Offset += Bulk_Data_Len; W_Length -= Bulk_Data_Len; // 缓冲区满时写入数据到存储设备 if (0 == (W_Length % Mass_Block_Size[lun])) { Block_Write_count = 0; MAL_Write(lun, W_Offset - Mass_Block_Size[lun], Data_Buffer, Mass_Block_Size[lun]); } CSW.dDataResidue -= Bulk_Data_Len; SetEPRxStatus(ENDP2, EP_RX_VALID); /* enable the next transaction*/ USB_Led_RW_ON(); } if ((W_Length == 0) || (Bot_State == BOT_CSW_Send)) { Block_Write_count = 0; Set_CSW(CSW_CMD_PASSED, SEND_CSW_ENABLE); TransferState = TXFR_IDLE; USB_Led_RW_OFF(); } }
/******************************************************************************* * Function Name : CBW_Decode * Description : Decode the received CBW and call the related SCSI command * routine. * Input : None. * Output : None. * Return : None. *******************************************************************************/ void CBW_Decode(void) { u32 Counter; for (Counter = 0; Counter < Data_Len; Counter++) { *((u8 *)&CBW + Counter) = Bulk_Data_Buff[Counter]; } CSW.dTag = CBW.dTag; CSW.dDataResidue = CBW.dDataLength; if (Data_Len != BOT_CBW_PACKET_LENGTH) { Bot_Abort(BOTH_DIR); /* reset the CBW.dSignature to desible the clear feature until receiving a Mass storage reset*/ CBW.dSignature = 0; Set_Scsi_Sense_Data(ILLEGAL_REQUEST, PARAMETER_LIST_LENGTH_ERROR); Set_CSW (CSW_CMD_FAILED, SEND_CSW_DISABLE); return; } if ((CBW.CB[0] == SCSI_READ10 ) || (CBW.CB[0] == SCSI_WRITE10 )) { /* Calculate Logical Block Address */ SCSI_LBA = (CBW.CB[2] << 24) | (CBW.CB[3] << 16) | (CBW.CB[4] << 8) | CBW.CB[5]; /* Calculate the Number of Blocks to transfer */ SCSI_BlkLen = (CBW.CB[7] << 8) | CBW.CB[8]; } if (CBW.dSignature == BOT_CBW_SIGNATURE) { /* Valid CBW */ if ((CBW.bLUN > Max_Lun) || (CBW.bCBLength < 1) || (CBW.bCBLength > 16)) { Bot_Abort(BOTH_DIR); Set_Scsi_Sense_Data(ILLEGAL_REQUEST, INVALID_FIELED_IN_COMMAND); Set_CSW (CSW_CMD_FAILED, SEND_CSW_DISABLE); } else { switch (CBW.CB[0]) { case SCSI_REQUEST_SENSE: SCSI_RequestSense_Cmd (); break; case SCSI_INQUIRY: SCSI_Inquiry_Cmd(); break; case SCSI_START_STOP_UNIT: SCSI_Start_Stop_Unit_Cmd(); break; case SCSI_ALLOW_MEDIUM_REMOVAL: SCSI_Start_Stop_Unit_Cmd(); break; case SCSI_MODE_SENSE6: SCSI_ModeSense6_Cmd (); break; case SCSI_MODE_SENSE10: SCSI_ModeSense10_Cmd (); break; case SCSI_READ_FORMAT_CAPACITIES: SCSI_ReadFormatCapacity_Cmd(); break; case SCSI_READ_CAPACITY10: SCSI_ReadCapacity10_Cmd(); break; case SCSI_TEST_UNIT_READY: SCSI_TestUnitReady_Cmd(); break; case SCSI_READ10: SCSI_Read10_Cmd(SCSI_LBA , SCSI_BlkLen); break; case SCSI_WRITE10: SCSI_Write10_Cmd(SCSI_LBA , SCSI_BlkLen); break; case SCSI_VERIFY10: SCSI_Verify10_Cmd(); break; case SCSI_FORMAT_UNIT: SCSI_Format_Cmd(); break; /*Unsupported command*/ case SCSI_MODE_SELECT10: SCSI_Mode_Select10_Cmd(); break; case SCSI_MODE_SELECT6: SCSI_Mode_Select6_Cmd(); break; case SCSI_SEND_DIAGNOSTIC: SCSI_Send_Diagnostic_Cmd(); break; case SCSI_READ6: SCSI_Read6_Cmd(); break; case SCSI_READ12: SCSI_Read12_Cmd(); break; case SCSI_READ16: SCSI_Read16_Cmd(); break; case SCSI_READ_CAPACITY16: SCSI_READ_CAPACITY16_Cmd(); break; case SCSI_WRITE6: SCSI_Write6_Cmd(); break; case SCSI_WRITE12: SCSI_Write12_Cmd(); break; case SCSI_WRITE16: SCSI_Write16_Cmd(); break; case SCSI_VERIFY12: SCSI_Verify12_Cmd(); break; case SCSI_VERIFY16: SCSI_Verify16_Cmd(); break; default: { Bot_Abort(BOTH_DIR); Set_Scsi_Sense_Data(ILLEGAL_REQUEST, INVALID_COMMAND); Set_CSW (CSW_CMD_FAILED, SEND_CSW_DISABLE); } } } } else { /* Invalid CBW */ Bot_Abort(BOTH_DIR); Set_Scsi_Sense_Data(ILLEGAL_REQUEST, INVALID_COMMAND); Set_CSW (CSW_CMD_FAILED, SEND_CSW_DISABLE); } }
/******************************************************************************* * Function Name : SCSI_Start_Stop_Unit_Cmd * Description : SCSI Start_Stop_Unit Command routine. * Input : None. * Output : None. * Return : None. *******************************************************************************/ void SCSI_Start_Stop_Unit_Cmd(uint8_t lun) { Set_CSW (CSW_CMD_PASSED, SEND_CSW_ENABLE); }
/******************************************************************************* * Function Name : SCSI_Valid_Cmd * Description : Valid Commands routine. * Input : None. * Output : None. * Return : None. *******************************************************************************/ void SCSI_TestUnitReady_Cmd(void) { MAL_GetStatus(); Set_CSW (CSW_CMD_PASSED, SEND_CSW_ENABLE); }
/******************************************************************************* * Function Name : SCSI_Start_Stop_Unit_Cmd * Description : SCSI Start_Stop_Unit Command routine. * Input : None. * Output : None. * Return : None. *******************************************************************************/ void SCSI_Start_Stop_Unit_Cmd(void) { Set_CSW (CSW_CMD_PASSED, SEND_CSW_ENABLE); }