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.
 */
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 =
		(MSInterfaceInfo->State.CommandBlock.SCSICommandData[2] <<
		 24) + (MSInterfaceInfo->State.CommandBlock.SCSICommandData[3] << 16) +
		(MSInterfaceInfo->State.CommandBlock.SCSICommandData[4] <<
		 8) + MSInterfaceInfo->State.CommandBlock.SCSICommandData[5];

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


	//xprintf("\nSCSI %c: ba=%d total=%d", IsDataRead ? 'R':'W', BlockAddress, TotalBlocks);

	/* Check if the block address is outside the maximum allowable value for the LUN */

	if (BlockAddress >= LUN_MEDIA_BLOCKS)
	{
		/* 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 * LUN_MEDIA_BLOCKS);
	#endif

	uint8_t* CallbackPreRead(const int LBA) {
		uint16_t bollocks;
		uint8_t *blockaddr = (uint8_t *)MassStorage_GetAddressInImage(BlockAddress + LBA, 1, &bollocks);
		return blockaddr;
	}
Esempio n. 2
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 true if the command completed successfully, false otherwise.
 */
static bool SCSI_Command_ReadWrite_10 (USB_ClassInfo_MS_Device_t* const MSInterfaceInfo, const bool IsDataRead)
{
	uint32_t BlockAddress;
	uint16_t TotalBlocks;
	//uint8_t buffer[VIRTUAL_MEMORY_BLOCK_SIZE];

	/* 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]);
	BlockAddress = (MSInterfaceInfo->State.CommandBlock.SCSICommandData[2] << 24) + (MSInterfaceInfo->State.CommandBlock.SCSICommandData[3] << 16) + (MSInterfaceInfo->State.CommandBlock.SCSICommandData[4] << 8) + MSInterfaceInfo->State.CommandBlock.SCSICommandData[5];

	/* 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]);
	TotalBlocks = (MSInterfaceInfo->State.CommandBlock.SCSICommandData[7] << 8) + MSInterfaceInfo->State.CommandBlock.SCSICommandData[8];

	/* Check if the block address is outside the maximum allowable value for the LUN */
	if (BlockAddress >= LUN_MEDIA_BLOCKS)
	{
		/* 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 * LUN_MEDIA_BLOCKS);
#endif
	
	/* Determine if the packet is a READ (10) or WRITE (10) command, call appropriate function */
#if 0
	if (IsDataRead == DATA_READ)
	{
		int i;
		for(i=0;i<TotalBlocks;i++)
		{
			while(!Endpoint_IsReadWriteAllowed());
			MassStorage_Read(((BlockAddress+i)*VIRTUAL_MEMORY_BLOCK_SIZE), buffer, VIRTUAL_MEMORY_BLOCK_SIZE);
			Endpoint_Write_Stream_LE(buffer, VIRTUAL_MEMORY_BLOCK_SIZE,NULL);
			Endpoint_ClearIN();
		}
	}
	else
	{
		int i;
		for(i=0;i<TotalBlocks;i++)
		{
			while(!Endpoint_IsReadWriteAllowed());
			Endpoint_Read_Stream_LE(buffer,VIRTUAL_MEMORY_BLOCK_SIZE,NULL);
			Endpoint_ClearOUT();
			MassStorage_Write((BlockAddress+i)*VIRTUAL_MEMORY_BLOCK_SIZE,buffer, VIRTUAL_MEMORY_BLOCK_SIZE);
		}
	}
#else
	uint32_t startaddr;
	uint16_t blocks, dummyblocks;

	startaddr = MassStorage_GetAddressInImage(BlockAddress, TotalBlocks, &blocks);
	if (blocks == 0)
		dummyblocks = TotalBlocks;
	else if (blocks < TotalBlocks)
		dummyblocks = TotalBlocks - blocks;
	else
		dummyblocks = 0;
	Endpoint_Streaming((uint8_t*) startaddr, VIRTUAL_MEMORY_BLOCK_SIZE, blocks, dummyblocks);
#endif
	/* Update the bytes transferred counter and succeed the command */
	MSInterfaceInfo->State.CommandBlock.DataTransferLength -= ((uint32_t) TotalBlocks * VIRTUAL_MEMORY_BLOCK_SIZE);

	return true;
}