/** 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; }
/** 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; }