X-Git-Url: http://git.linex4red.de/pub/USBasp.git/blobdiff_plain/cb779e3d7d32d7c43e0a45bb526de0a04135b0c7..bcb627e1a1bb9f013670d981ead2db97d7c70608:/Projects/Incomplete/StandaloneProgrammer/Lib/SCSI.c diff --git a/Projects/Incomplete/StandaloneProgrammer/Lib/SCSI.c b/Projects/Incomplete/StandaloneProgrammer/Lib/SCSI.c index 7b2a8fa83..04469cad1 100644 --- a/Projects/Incomplete/StandaloneProgrammer/Lib/SCSI.c +++ b/Projects/Incomplete/StandaloneProgrammer/Lib/SCSI.c @@ -1,13 +1,13 @@ /* LUFA Library - Copyright (C) Dean Camera, 2010. + Copyright (C) Dean Camera, 2011. dean [at] fourwalledcubicle [dot] com www.lufa-lib.org */ /* - Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted @@ -42,7 +42,7 @@ /** Structure to hold the SCSI response data to a SCSI INQUIRY command. This gives information about the device's * features and capabilities. */ -SCSI_Inquiry_Response_t InquiryData = +static const SCSI_Inquiry_Response_t InquiryData = { .DeviceType = DEVICE_TYPE_BLOCK, .PeripheralQualifier = 0, @@ -74,7 +74,7 @@ SCSI_Inquiry_Response_t InquiryData = /** Structure to hold the sense data for the last issued SCSI command, which is returned to the host after a SCSI REQUEST SENSE * command is issued. This gives information on exactly why the last command failed to complete. */ -SCSI_Request_Sense_Response_t SenseData = +static SCSI_Request_Sense_Response_t SenseData = { .ResponseCode = 0x70, .AdditionalLength = 0x0A, @@ -114,6 +114,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: @@ -152,8 +155,7 @@ bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) static bool SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) { uint16_t AllocationLength = SwapEndian_16(*(uint16_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[3]); - uint16_t BytesTransferred = (AllocationLength < sizeof(InquiryData))? AllocationLength : - sizeof(InquiryData); + uint16_t BytesTransferred = MIN(AllocationLength, sizeof(InquiryData)); /* Only the standard INQUIRY data is supported, check if any optional INQUIRY bits set */ if ((MSInterfaceInfo->State.CommandBlock.SCSICommandData[1] & ((1 << 0) | (1 << 1))) || @@ -167,12 +169,10 @@ static bool SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInf return false; } - Endpoint_Write_Stream_LE(&InquiryData, BytesTransferred, NO_STREAM_CALLBACK); - - uint8_t PadBytes[AllocationLength - BytesTransferred]; + Endpoint_Write_Stream_LE(&InquiryData, BytesTransferred, NULL); /* Pad out remaining bytes with 0x00 */ - Endpoint_Write_Stream_LE(&PadBytes, sizeof(PadBytes), NO_STREAM_CALLBACK); + Endpoint_Null_Stream((AllocationLength - BytesTransferred), NULL); /* Finalize the stream transfer to send the last packet */ Endpoint_ClearIN(); @@ -193,12 +193,10 @@ static bool SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInf static bool SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) { uint8_t AllocationLength = MSInterfaceInfo->State.CommandBlock.SCSICommandData[4]; - uint8_t BytesTransferred = (AllocationLength < sizeof(SenseData))? AllocationLength : sizeof(SenseData); - - uint8_t PadBytes[AllocationLength - BytesTransferred]; + uint8_t BytesTransferred = MIN(AllocationLength, sizeof(SenseData)); - Endpoint_Write_Stream_LE(&SenseData, BytesTransferred, NO_STREAM_CALLBACK); - Endpoint_Write_Stream_LE(&PadBytes, sizeof(PadBytes), NO_STREAM_CALLBACK); + Endpoint_Write_Stream_LE(&SenseData, BytesTransferred, NULL); + Endpoint_Null_Stream((AllocationLength - BytesTransferred), NULL); Endpoint_ClearIN(); /* Succeed the command and update the bytes transferred counter */ @@ -219,8 +217,8 @@ static bool SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInt uint32_t LastBlockAddressInLUN = (VIRTUAL_MEMORY_BLOCKS - 1); uint32_t MediaBlockSize = VIRTUAL_MEMORY_BLOCK_SIZE; - Endpoint_Write_Stream_BE(&LastBlockAddressInLUN, sizeof(LastBlockAddressInLUN), NO_STREAM_CALLBACK); - Endpoint_Write_Stream_BE(&MediaBlockSize, sizeof(MediaBlockSize), NO_STREAM_CALLBACK); + Endpoint_Write_Stream_BE(&LastBlockAddressInLUN, sizeof(LastBlockAddressInLUN), NULL); + Endpoint_Write_Stream_BE(&MediaBlockSize, sizeof(MediaBlockSize), NULL); Endpoint_ClearIN(); /* Succeed the command and update the bytes transferred counter */ @@ -282,6 +280,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]); @@ -298,7 +307,7 @@ static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfa return false; } - + /* Determine if the packet is a READ (10) or WRITE (10) command, call appropriate function */ if (IsDataRead == DATA_READ) DataflashManager_ReadBlocks(MSInterfaceInfo, BlockAddress, TotalBlocks); @@ -310,5 +319,26 @@ static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfa return true; } -#endif +/** 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_8(0x00); + Endpoint_Write_8(0x00); + Endpoint_Write_8(DISK_READ_ONLY ? 0x80 : 0x00); + Endpoint_Write_8(0x00); + Endpoint_ClearIN(); + + /* Update the bytes transferred counter and succeed the command */ + MSInterfaceInfo->State.CommandBlock.DataTransferLength -= 4; + + return true; +} +#endif \ No newline at end of file