Esempio n. 1
0
/** Command processing for an issued SCSI READ (10) or WRITE (10) command. This command reads in the block start address
 *  and total number of blocks to process, then calls the appropriate low-level Dataflash routine to handle the actual
 *  reading and writing of the data.
 *
 *  \param[in] MSInterfaceInfo  Pointer to the Mass Storage class interface structure that the command is associated with
 *  \param[in] IsDataRead  Indicates if the command is a READ (10) command or WRITE (10) command (DATA_READ or DATA_WRITE)
 *
 *  \return Boolean \c true if the command completed successfully, \c false otherwise.
 */
static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
                                      const bool IsDataRead)
{
	uint32_t BlockAddress;
	uint16_t TotalBlocks;

	/* Check if the disk is write protected or not */
	if ((IsDataRead == DATA_WRITE) && DISK_READ_ONLY)
	{
		/* Block address is invalid, update SENSE key and return command fail */
		SCSI_SET_SENSE(SCSI_SENSE_KEY_DATA_PROTECT,
		               SCSI_ASENSE_WRITE_PROTECTED,
		               SCSI_ASENSEQ_NO_QUALIFIER);

		return false;
	}

	/* Load in the 32-bit block address (SCSI uses big-endian, so have to reverse the byte order) */
	BlockAddress = SwapEndian_32(*(uint32_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[2]);

	/* Load in the 16-bit total blocks (SCSI uses big-endian, so have to reverse the byte order) */
	TotalBlocks  = SwapEndian_16(*(uint16_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[7]);

	/* Check if the block address is outside the maximum allowable value for the LUN */
	if (BlockAddress >= MMC_MediaBlocks())
	{
		/* Block address is invalid, update SENSE key and return command fail */
		SCSI_SET_SENSE(SCSI_SENSE_KEY_ILLEGAL_REQUEST,
		               SCSI_ASENSE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE,
		               SCSI_ASENSEQ_NO_QUALIFIER);

		return false;
	}

	#if (TOTAL_LUNS > 1)
	/* Adjust the given block address to the real media address based on the selected LUN */
	BlockAddress += ((uint32_t)MSInterfaceInfo->State.CommandBlock.LUN * MMC_MediaBlocks());
	#endif

	/* Determine if the packet is a READ (10) or WRITE (10) command, call appropriate function */
	if (IsDataRead == DATA_READ)
	  MMC_ReadBlocks(MSInterfaceInfo, BlockAddress, TotalBlocks);
	else
	  MMC_WriteBlocks(MSInterfaceInfo, BlockAddress, TotalBlocks);

	/* Update the bytes transferred counter and succeed the command */
	MSInterfaceInfo->State.CommandBlock.DataTransferLength -= ((uint32_t)TotalBlocks * VIRTUAL_MEMORY_BLOCK_SIZE);

	return true;
}
/**
 * @brief Reads data from EMMC block device manager
 *
 * @param[in]     FPDConfig_p Flash device configuration of BDM
 * @param[in]     Pos         EMMC sector where reading should start.
 * @param[in]     Length      Number of sectors to read.
 * @param[in,out] FirstBad_p  Not used for eMMC.
 * @param[out]    Data_p      Output buffer.
 *
 * @return ErrorCode_e Forwards the response from EMMC module.
 *
 * @remark This function should be called only from BDM module.
 */
ErrorCode_e Do_BDM_EMMC_Read(FPD_Config_t *const FPDConfig_p, uint32 Pos, uint32 Length, uint32 *FirstBad_p, uint8 *Data_p)
{
    ErrorCode_e     ReturnValue = E_GENERAL_FATAL_ERROR;
    t_mmc_error     MMC_Error;
    void *TmpData_p = Data_p;

    IDENTIFIER_NOT_USED(FirstBad_p);

    // MMC interface requires uint32* for data, Data_p must be 32-bit aligned
    IS_ALIGNED((uint32)Data_p);

    // Jedec 84-A44 : Size < 2GB => byte addressing
    if (!FPDConfig_p->HC_Card) {
        Pos *= MMC_ADDRESS_MODE_FACTOR;
    }

    // Typecast on Data_p OK, alignment checked above
    MMC_Error = MMC_ReadBlocks(1, Pos, (uint32 *)TmpData_p, FPDConfig_p->PageSize, Length, FPDConfig_p->DeviceId);
    VERIFY(MMC_OK == MMC_Error, E_BDM_READ_FAILED);

    ReturnValue = E_SUCCESS;
ErrorExit:
    return ReturnValue;
}