From 9f7883fa2b78fd7907162987fc65b71d3c6b19fa Mon Sep 17 00:00:00 2001 From: Dean Camera Date: Fri, 26 Nov 2010 04:16:47 +0000 Subject: Added ability to write protect Mass Storage disk write operations from the host OS. --- Demos/Device/ClassDriver/MassStorage/Lib/SCSI.c | 37 +++++++++++++++++++++- Demos/Device/ClassDriver/MassStorage/Lib/SCSI.h | 1 + Demos/Device/ClassDriver/MassStorage/MassStorage.h | 3 ++ 3 files changed, 40 insertions(+), 1 deletion(-) (limited to 'Demos/Device/ClassDriver/MassStorage') diff --git a/Demos/Device/ClassDriver/MassStorage/Lib/SCSI.c b/Demos/Device/ClassDriver/MassStorage/Lib/SCSI.c index 5e0a82be2..ac6c9e7c7 100644 --- a/Demos/Device/ClassDriver/MassStorage/Lib/SCSI.c +++ b/Demos/Device/ClassDriver/MassStorage/Lib/SCSI.c @@ -113,6 +113,9 @@ bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) case SCSI_CMD_READ_10: CommandSuccess = SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_READ); break; + case SCSI_CMD_MODE_SENSE_6: + CommandSuccess = SCSI_Command_ModeSense_6(MSInterfaceInfo); + break; case SCSI_CMD_TEST_UNIT_READY: case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL: case SCSI_CMD_VERIFY_10: @@ -281,6 +284,17 @@ static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfa 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]); @@ -302,7 +316,7 @@ static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfa /* 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 (IsDataRead == DATA_READ) DataflashManager_ReadBlocks(MSInterfaceInfo, BlockAddress, TotalBlocks); @@ -315,3 +329,24 @@ static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfa return true; } +/** Command processing for an issued SCSI MODE SENSE (6) command. This command returns various informational pages about + * the SCSI device, as well as the device's Write Protect status. + * + * \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with + * + * \return Boolean true if the command completed successfully, false otherwise. + */ +static bool SCSI_Command_ModeSense_6(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) +{ + /* Send an empty header response with the Write Protect flag status */ + Endpoint_Write_Byte(0x00); + Endpoint_Write_Byte(0x00); + Endpoint_Write_Byte(DISK_READ_ONLY ? 0x80 : 0x00); + Endpoint_Write_Byte(0x00); + Endpoint_ClearIN(); + + /* Update the bytes transferred counter and succeed the command */ + MSInterfaceInfo->State.CommandBlock.DataTransferLength -= 4; + + return true; +} diff --git a/Demos/Device/ClassDriver/MassStorage/Lib/SCSI.h b/Demos/Device/ClassDriver/MassStorage/Lib/SCSI.h index e8f5eb65e..6f2e19d39 100644 --- a/Demos/Device/ClassDriver/MassStorage/Lib/SCSI.h +++ b/Demos/Device/ClassDriver/MassStorage/Lib/SCSI.h @@ -81,6 +81,7 @@ static bool SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo); static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo, const bool IsDataRead); + static bool SCSI_Command_ModeSense_6(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo); #endif #endif diff --git a/Demos/Device/ClassDriver/MassStorage/MassStorage.h b/Demos/Device/ClassDriver/MassStorage/MassStorage.h index f7ac3636f..63a864288 100644 --- a/Demos/Device/ClassDriver/MassStorage/MassStorage.h +++ b/Demos/Device/ClassDriver/MassStorage/MassStorage.h @@ -73,6 +73,9 @@ /** Blocks in each LUN, calculated from the total capacity divided by the total number of Logical Units in the device. */ #define LUN_MEDIA_BLOCKS (VIRTUAL_MEMORY_BLOCKS / TOTAL_LUNS) + + /** Indicates if the disk is write protected or not. */ + #define DISK_READ_ONLY false /* Function Prototypes: */ void SetupHardware(void); -- cgit v1.2.3