diff --git a/Demos/Device/ClassDriver/MassStorage/Lib/SCSI.c b/Demos/Device/ClassDriver/MassStorage/Lib/SCSI.c index 4efbbc0a79..fed57f7b93 100644 --- a/Demos/Device/ClassDriver/MassStorage/Lib/SCSI.c +++ b/Demos/Device/ClassDriver/MassStorage/Lib/SCSI.c @@ -85,39 +85,39 @@ SCSI_Request_Sense_Response_t SenseData = * a command failure due to a ILLEGAL REQUEST. * * \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 */ bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) { - /* Set initial sense data, before the requested command is processed */ - SCSI_SET_SENSE(SCSI_SENSE_KEY_GOOD, - SCSI_ASENSE_NO_ADDITIONAL_INFORMATION, - SCSI_ASENSEQ_NO_QUALIFIER); - + bool CommandSuccess = false; + /* Run the appropriate SCSI command hander function based on the passed command */ switch (MSInterfaceInfo->State.CommandBlock.SCSICommandData[0]) { case SCSI_CMD_INQUIRY: - SCSI_Command_Inquiry(MSInterfaceInfo); + CommandSuccess = SCSI_Command_Inquiry(MSInterfaceInfo); break; case SCSI_CMD_REQUEST_SENSE: - SCSI_Command_Request_Sense(MSInterfaceInfo); + CommandSuccess = SCSI_Command_Request_Sense(MSInterfaceInfo); break; case SCSI_CMD_READ_CAPACITY_10: - SCSI_Command_Read_Capacity_10(MSInterfaceInfo); + CommandSuccess = SCSI_Command_Read_Capacity_10(MSInterfaceInfo); break; case SCSI_CMD_SEND_DIAGNOSTIC: - SCSI_Command_Send_Diagnostic(MSInterfaceInfo); + CommandSuccess = SCSI_Command_Send_Diagnostic(MSInterfaceInfo); break; case SCSI_CMD_WRITE_10: - SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_WRITE); + CommandSuccess = SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_WRITE); break; case SCSI_CMD_READ_10: - SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_READ); + CommandSuccess = SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_READ); break; case SCSI_CMD_TEST_UNIT_READY: case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL: case SCSI_CMD_VERIFY_10: /* These commands should just succeed, no handling required */ + CommandSuccess = true; MSInterfaceInfo->State.CommandBlock.DataTransferLength = 0; break; default: @@ -128,15 +128,27 @@ bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) break; } - return (SenseData.SenseKey == SCSI_SENSE_KEY_GOOD); + /* Check if command was successfully processed */ + if (CommandSuccess) + { + SCSI_SET_SENSE(SCSI_SENSE_KEY_GOOD, + SCSI_ASENSE_NO_ADDITIONAL_INFORMATION, + SCSI_ASENSEQ_NO_QUALIFIER); + + return true; + } + + return false; } /** Command processing for an issued SCSI INQUIRY command. This command returns information about the device's features * and capabilities to the host. * * \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 void SCSI_Command_Inquiry(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 : @@ -151,7 +163,7 @@ static void SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInf SCSI_ASENSE_INVALID_FIELD_IN_CDB, SCSI_ASENSEQ_NO_QUALIFIER); - return; + return false; } Endpoint_Write_Stream_LE(&InquiryData, BytesTransferred, NO_STREAM_CALLBACK); @@ -166,14 +178,18 @@ static void SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInf /* Succeed the command and update the bytes transferred counter */ MSInterfaceInfo->State.CommandBlock.DataTransferLength -= BytesTransferred; + + return true; } /** Command processing for an issued SCSI REQUEST SENSE command. This command returns information about the last issued command, * including the error code and additional error information so that the host can determine why a command failed to complete. * * \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 void SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) +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); @@ -181,19 +197,23 @@ static void SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterf uint8_t PadBytes[AllocationLength - BytesTransferred]; Endpoint_Write_Stream_LE(&SenseData, BytesTransferred, NO_STREAM_CALLBACK); - Endpoint_Write_Stream_LE(&PadBytes, (AllocationLength - BytesTransferred), NO_STREAM_CALLBACK); + Endpoint_Write_Stream_LE(&PadBytes, sizeof(PadBytes), NO_STREAM_CALLBACK); Endpoint_ClearIN(); /* Succeed the command and update the bytes transferred counter */ MSInterfaceInfo->State.CommandBlock.DataTransferLength -= BytesTransferred; + + return true; } /** Command processing for an issued SCSI READ CAPACITY (10) command. This command returns information about the device's capacity * on the selected Logical Unit (drive), as a number of OS-sized blocks. * * \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 void SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) +static bool SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) { uint32_t LastBlockAddressInLUN = (LUN_MEDIA_BLOCKS - 1); uint32_t MediaBlockSize = VIRTUAL_MEMORY_BLOCK_SIZE; @@ -204,6 +224,8 @@ static void SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInt /* Succeed the command and update the bytes transferred counter */ MSInterfaceInfo->State.CommandBlock.DataTransferLength -= 8; + + return true; } /** Command processing for an issued SCSI SEND DIAGNOSTIC command. This command performs a quick check of the Dataflash ICs on the @@ -211,8 +233,10 @@ static void SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInt * supported. * * \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 void SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) +static bool SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) { /* Check to see if the SELF TEST bit is not set */ if (!(MSInterfaceInfo->State.CommandBlock.SCSICommandData[1] & (1 << 2))) @@ -222,7 +246,7 @@ static void SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInte SCSI_ASENSE_INVALID_FIELD_IN_CDB, SCSI_ASENSEQ_NO_QUALIFIER); - return; + return false; } /* Check to see if all attached Dataflash ICs are functional */ @@ -233,11 +257,13 @@ static void SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInte SCSI_ASENSE_NO_ADDITIONAL_INFORMATION, SCSI_ASENSEQ_NO_QUALIFIER); - return; + return false; } /* Succeed the command and update the bytes transferred counter */ MSInterfaceInfo->State.CommandBlock.DataTransferLength = 0; + + return true; } /** Command processing for an issued SCSI READ (10) or WRITE (10) command. This command reads in the block start address @@ -246,12 +272,20 @@ static void SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInte * * \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 void SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo, +static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo, const bool IsDataRead) { - uint32_t BlockAddress = SwapEndian_32(*(uint32_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[2]); - uint16_t TotalBlocks = SwapEndian_16(*(uint16_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[7]); + uint32_t BlockAddress; + uint16_t TotalBlocks; + + /* 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 >= LUN_MEDIA_BLOCKS) @@ -261,7 +295,7 @@ static void SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfa SCSI_ASENSE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, SCSI_ASENSEQ_NO_QUALIFIER); - return; + return false; } #if (TOTAL_LUNS > 1) @@ -277,4 +311,6 @@ static void SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfa /* Update the bytes transferred counter and succeed the command */ MSInterfaceInfo->State.CommandBlock.DataTransferLength -= ((uint32_t)TotalBlocks * VIRTUAL_MEMORY_BLOCK_SIZE); + + return true; } diff --git a/Demos/Device/ClassDriver/MassStorage/Lib/SCSI.h b/Demos/Device/ClassDriver/MassStorage/Lib/SCSI.h index 0c00cfb4ff..44ccb98906 100644 --- a/Demos/Device/ClassDriver/MassStorage/Lib/SCSI.h +++ b/Demos/Device/ClassDriver/MassStorage/Lib/SCSI.h @@ -56,9 +56,9 @@ * \param[in] acode New SCSI additional sense key to set the additional sense code to * \param[in] aqual New SCSI additional sense key qualifier to set the additional sense qualifier code to */ - #define SCSI_SET_SENSE(key, acode, aqual) MACROS{ SenseData.SenseKey = (key); \ - SenseData.AdditionalSenseCode = (acode); \ - SenseData.AdditionalSenseQualifier = (aqual); }MACROE + #define SCSI_SET_SENSE(Key, Acode, Aqual) MACROS{ SenseData.SenseKey = (Key); \ + SenseData.AdditionalSenseCode = (Acode); \ + SenseData.AdditionalSenseQualifier = (Aqual); }MACROE /** Macro for the \ref SCSI_Command_ReadWrite_10() function, to indicate that data is to be read from the storage medium. */ #define DATA_READ true @@ -76,11 +76,11 @@ bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo); #if defined(INCLUDE_FROM_SCSI_C) - static void SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo); - static void SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo); - static void SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo); - static void SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo); - static void SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo, + static bool SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo); + static bool SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo); + static bool SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo); + 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); #endif diff --git a/Demos/Device/ClassDriver/MassStorageKeyboard/Lib/DataflashManager.c b/Demos/Device/ClassDriver/MassStorageKeyboard/Lib/DataflashManager.c index 445082f247..ce2ac81514 100644 --- a/Demos/Device/ClassDriver/MassStorageKeyboard/Lib/DataflashManager.c +++ b/Demos/Device/ClassDriver/MassStorageKeyboard/Lib/DataflashManager.c @@ -498,3 +498,36 @@ void DataflashManager_ResetDataflashProtections(void) /* Deselect current Dataflash chip */ Dataflash_DeselectChip(); } + +/** Performs a simple test on the attached Dataflash IC(s) to ensure that they are working. + * + * \return Boolean true if all media chips are working, false otherwise + */ +bool DataflashManager_CheckDataflashOperation(void) +{ + uint8_t ReturnByte; + + /* Test first Dataflash IC is present and responding to commands */ + Dataflash_SelectChip(DATAFLASH_CHIP1); + Dataflash_SendByte(DF_CMD_READMANUFACTURERDEVICEINFO); + ReturnByte = Dataflash_ReceiveByte(); + Dataflash_DeselectChip(); + + /* If returned data is invalid, fail the command */ + if (ReturnByte != DF_MANUFACTURER_ATMEL) + return false; + + #if (DATAFLASH_TOTALCHIPS == 2) + /* Test second Dataflash IC is present and responding to commands */ + Dataflash_SelectChip(DATAFLASH_CHIP2); + Dataflash_SendByte(DF_CMD_READMANUFACTURERDEVICEINFO); + ReturnByte = Dataflash_ReceiveByte(); + Dataflash_DeselectChip(); + + /* If returned data is invalid, fail the command */ + if (ReturnByte != DF_MANUFACTURER_ATMEL) + return false; + #endif + + return true; +} diff --git a/Demos/Device/ClassDriver/MassStorageKeyboard/Lib/DataflashManager.h b/Demos/Device/ClassDriver/MassStorageKeyboard/Lib/DataflashManager.h index 694867f0e0..d5a9fd5b04 100644 --- a/Demos/Device/ClassDriver/MassStorageKeyboard/Lib/DataflashManager.h +++ b/Demos/Device/ClassDriver/MassStorageKeyboard/Lib/DataflashManager.h @@ -83,5 +83,6 @@ uint16_t TotalBlocks, uint8_t* BufferPtr) ATTR_NON_NULL_PTR_ARG(3); void DataflashManager_ResetDataflashProtections(void); + bool DataflashManager_CheckDataflashOperation(void); #endif diff --git a/Demos/Device/ClassDriver/MassStorageKeyboard/Lib/SCSI.c b/Demos/Device/ClassDriver/MassStorageKeyboard/Lib/SCSI.c index 0dac650909..fed57f7b93 100644 --- a/Demos/Device/ClassDriver/MassStorageKeyboard/Lib/SCSI.c +++ b/Demos/Device/ClassDriver/MassStorageKeyboard/Lib/SCSI.c @@ -85,6 +85,8 @@ SCSI_Request_Sense_Response_t SenseData = * a command failure due to a ILLEGAL REQUEST. * * \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 */ bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) { @@ -236,8 +238,6 @@ static bool SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInt */ static bool SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) { - uint8_t ReturnByte; - /* Check to see if the SELF TEST bit is not set */ if (!(MSInterfaceInfo->State.CommandBlock.SCSICommandData[1] & (1 << 2))) { @@ -249,32 +249,8 @@ static bool SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInte return false; } - /* Test first Dataflash IC is present and responding to commands */ - Dataflash_SelectChip(DATAFLASH_CHIP1); - Dataflash_SendByte(DF_CMD_READMANUFACTURERDEVICEINFO); - ReturnByte = Dataflash_ReceiveByte(); - Dataflash_DeselectChip(); - - /* If returned data is invalid, fail the command */ - if (ReturnByte != DF_MANUFACTURER_ATMEL) - { - /* Update SENSE key with a hardware error condition and return command fail */ - SCSI_SET_SENSE(SCSI_SENSE_KEY_HARDWARE_ERROR, - SCSI_ASENSE_NO_ADDITIONAL_INFORMATION, - SCSI_ASENSEQ_NO_QUALIFIER); - - return false; - } - - #if (DATAFLASH_TOTALCHIPS == 2) - /* Test second Dataflash IC is present and responding to commands */ - Dataflash_SelectChip(DATAFLASH_CHIP2); - Dataflash_SendByte(DF_CMD_READMANUFACTURERDEVICEINFO); - ReturnByte = Dataflash_ReceiveByte(); - Dataflash_DeselectChip(); - - /* If returned data is invalid, fail the command */ - if (ReturnByte != DF_MANUFACTURER_ATMEL) + /* Check to see if all attached Dataflash ICs are functional */ + if (!(DataflashManager_CheckDataflashOperation())) { /* Update SENSE key with a hardware error condition and return command fail */ SCSI_SET_SENSE(SCSI_SENSE_KEY_HARDWARE_ERROR, @@ -283,7 +259,6 @@ static bool SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInte return false; } - #endif /* Succeed the command and update the bytes transferred counter */ MSInterfaceInfo->State.CommandBlock.DataTransferLength = 0; diff --git a/Demos/Device/ClassDriver/MassStorageKeyboard/Lib/SCSI.h b/Demos/Device/ClassDriver/MassStorageKeyboard/Lib/SCSI.h index 6025d866f0..96489ab82d 100644 --- a/Demos/Device/ClassDriver/MassStorageKeyboard/Lib/SCSI.h +++ b/Demos/Device/ClassDriver/MassStorageKeyboard/Lib/SCSI.h @@ -46,7 +46,6 @@ #include "MassStorageKeyboard.h" #include "Descriptors.h" #include "DataflashManager.h" - #include "SCSI_Codes.h" /* Macros: */ /** Macro to set the current SCSI sense data to the given key, additional sense code and additional sense qualifier. This @@ -57,9 +56,9 @@ * \param[in] acode New SCSI additional sense key to set the additional sense code to * \param[in] aqual New SCSI additional sense key qualifier to set the additional sense qualifier code to */ - #define SCSI_SET_SENSE(key, acode, aqual) MACROS{ SenseData.SenseKey = key; \ - SenseData.AdditionalSenseCode = acode; \ - SenseData.AdditionalSenseQualifier = aqual; }MACROE + #define SCSI_SET_SENSE(Key, Acode, Aqual) MACROS{ SenseData.SenseKey = (Key); \ + SenseData.AdditionalSenseCode = (Acode); \ + SenseData.AdditionalSenseQualifier = (Aqual); }MACROE /** Macro for the \ref SCSI_Command_ReadWrite_10() function, to indicate that data is to be read from the storage medium. */ #define DATA_READ true diff --git a/Demos/Device/ClassDriver/MassStorageKeyboard/Lib/SCSI_Codes.h b/Demos/Device/ClassDriver/MassStorageKeyboard/Lib/SCSI_Codes.h deleted file mode 100644 index 5b6b76ac87..0000000000 --- a/Demos/Device/ClassDriver/MassStorageKeyboard/Lib/SCSI_Codes.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2010. - - dean [at] fourwalledcubicle [dot] com - www.fourwalledcubicle.com -*/ - -/* - Copyright 2010 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 - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaim all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -/** \file - * - * Header containing macros for possible SCSI commands and SENSE data. Refer to - * the SCSI standard documentation for more information on each SCSI command and - * the SENSE data. - */ - -#ifndef _SCSI_CODES_H_ -#define _SCSI_CODES_H_ - - /* Macros: */ - #define SCSI_CMD_INQUIRY 0x12 - #define SCSI_CMD_REQUEST_SENSE 0x03 - #define SCSI_CMD_TEST_UNIT_READY 0x00 - #define SCSI_CMD_READ_CAPACITY_10 0x25 - #define SCSI_CMD_SEND_DIAGNOSTIC 0x1D - #define SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1E - #define SCSI_CMD_WRITE_10 0x2A - #define SCSI_CMD_READ_10 0x28 - #define SCSI_CMD_WRITE_6 0x0A - #define SCSI_CMD_READ_6 0x08 - #define SCSI_CMD_VERIFY_10 0x2F - #define SCSI_CMD_MODE_SENSE_6 0x1A - #define SCSI_CMD_MODE_SENSE_10 0x5A - - #define SCSI_SENSE_KEY_GOOD 0x00 - #define SCSI_SENSE_KEY_RECOVERED_ERROR 0x01 - #define SCSI_SENSE_KEY_NOT_READY 0x02 - #define SCSI_SENSE_KEY_MEDIUM_ERROR 0x03 - #define SCSI_SENSE_KEY_HARDWARE_ERROR 0x04 - #define SCSI_SENSE_KEY_ILLEGAL_REQUEST 0x05 - #define SCSI_SENSE_KEY_UNIT_ATTENTION 0x06 - #define SCSI_SENSE_KEY_DATA_PROTECT 0x07 - #define SCSI_SENSE_KEY_BLANK_CHECK 0x08 - #define SCSI_SENSE_KEY_VENDOR_SPECIFIC 0x09 - #define SCSI_SENSE_KEY_COPY_ABORTED 0x0A - #define SCSI_SENSE_KEY_ABORTED_COMMAND 0x0B - #define SCSI_SENSE_KEY_VOLUME_OVERFLOW 0x0D - #define SCSI_SENSE_KEY_MISCOMPARE 0x0E - - #define SCSI_ASENSE_NO_ADDITIONAL_INFORMATION 0x00 - #define SCSI_ASENSE_LOGICAL_UNIT_NOT_READY 0x04 - #define SCSI_ASENSE_INVALID_FIELD_IN_CDB 0x24 - #define SCSI_ASENSE_WRITE_PROTECTED 0x27 - #define SCSI_ASENSE_FORMAT_ERROR 0x31 - #define SCSI_ASENSE_INVALID_COMMAND 0x20 - #define SCSI_ASENSE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE 0x21 - #define SCSI_ASENSE_MEDIUM_NOT_PRESENT 0x3A - - #define SCSI_ASENSEQ_NO_QUALIFIER 0x00 - #define SCSI_ASENSEQ_FORMAT_COMMAND_FAILED 0x01 - #define SCSI_ASENSEQ_INITIALIZING_COMMAND_REQUIRED 0x02 - #define SCSI_ASENSEQ_OPERATION_IN_PROGRESS 0x07 - -#endif diff --git a/Demos/Device/LowLevel/MassStorage/Lib/SCSI.c b/Demos/Device/LowLevel/MassStorage/Lib/SCSI.c index 4d2323e0df..76005952f1 100644 --- a/Demos/Device/LowLevel/MassStorage/Lib/SCSI.c +++ b/Demos/Device/LowLevel/MassStorage/Lib/SCSI.c @@ -88,36 +88,34 @@ SCSI_Request_Sense_Response_t SenseData = */ bool SCSI_DecodeSCSICommand(void) { - /* Set initial sense data, before the requested command is processed */ - SCSI_SET_SENSE(SCSI_SENSE_KEY_GOOD, - SCSI_ASENSE_NO_ADDITIONAL_INFORMATION, - SCSI_ASENSEQ_NO_QUALIFIER); + bool CommandSuccess = false; /* Run the appropriate SCSI command hander function based on the passed command */ switch (CommandBlock.SCSICommandData[0]) { case SCSI_CMD_INQUIRY: - SCSI_Command_Inquiry(); + CommandSuccess = SCSI_Command_Inquiry(); break; case SCSI_CMD_REQUEST_SENSE: - SCSI_Command_Request_Sense(); + CommandSuccess = SCSI_Command_Request_Sense(); break; case SCSI_CMD_READ_CAPACITY_10: - SCSI_Command_Read_Capacity_10(); + CommandSuccess = SCSI_Command_Read_Capacity_10(); break; case SCSI_CMD_SEND_DIAGNOSTIC: - SCSI_Command_Send_Diagnostic(); + CommandSuccess = SCSI_Command_Send_Diagnostic(); break; case SCSI_CMD_WRITE_10: - SCSI_Command_ReadWrite_10(DATA_WRITE); + CommandSuccess = SCSI_Command_ReadWrite_10(DATA_WRITE); break; case SCSI_CMD_READ_10: - SCSI_Command_ReadWrite_10(DATA_READ); + CommandSuccess = SCSI_Command_ReadWrite_10(DATA_READ); break; case SCSI_CMD_TEST_UNIT_READY: case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL: case SCSI_CMD_VERIFY_10: /* These commands should just succeed, no handling required */ + CommandSuccess = true; CommandBlock.DataTransferLength = 0; break; default: @@ -128,13 +126,25 @@ bool SCSI_DecodeSCSICommand(void) break; } - return (SenseData.SenseKey == SCSI_SENSE_KEY_GOOD); + /* Check if command was successfully processed */ + if (CommandSuccess) + { + SCSI_SET_SENSE(SCSI_SENSE_KEY_GOOD, + SCSI_ASENSE_NO_ADDITIONAL_INFORMATION, + SCSI_ASENSEQ_NO_QUALIFIER); + + return true; + } + + return false; } /** Command processing for an issued SCSI INQUIRY command. This command returns information about the device's features * and capabilities to the host. + * + * \return Boolean true if the command completed successfully, false otherwise. */ -static void SCSI_Command_Inquiry(void) +static bool SCSI_Command_Inquiry(void) { uint16_t AllocationLength = SwapEndian_16(*(uint16_t*)&CommandBlock.SCSICommandData[3]); uint16_t BytesTransferred = (AllocationLength < sizeof(InquiryData))? AllocationLength : @@ -149,7 +159,7 @@ static void SCSI_Command_Inquiry(void) SCSI_ASENSE_INVALID_FIELD_IN_CDB, SCSI_ASENSEQ_NO_QUALIFIER); - return; + return false; } /* Write the INQUIRY data to the endpoint */ @@ -165,12 +175,16 @@ static void SCSI_Command_Inquiry(void) /* Succeed the command and update the bytes transferred counter */ CommandBlock.DataTransferLength -= BytesTransferred; + + return true; } /** Command processing for an issued SCSI REQUEST SENSE command. This command returns information about the last issued command, * including the error code and additional error information so that the host can determine why a command failed to complete. + * + * \return Boolean true if the command completed successfully, false otherwise. */ -static void SCSI_Command_Request_Sense(void) +static bool SCSI_Command_Request_Sense(void) { uint8_t AllocationLength = CommandBlock.SCSICommandData[4]; uint8_t BytesTransferred = (AllocationLength < sizeof(SenseData))? AllocationLength : sizeof(SenseData); @@ -188,12 +202,16 @@ static void SCSI_Command_Request_Sense(void) /* Succeed the command and update the bytes transferred counter */ CommandBlock.DataTransferLength -= BytesTransferred; + + return true; } /** Command processing for an issued SCSI READ CAPACITY (10) command. This command returns information about the device's capacity * on the selected Logical Unit (drive), as a number of OS-sized blocks. + * + * \return Boolean true if the command completed successfully, false otherwise. */ -static void SCSI_Command_Read_Capacity_10(void) +static bool SCSI_Command_Read_Capacity_10(void) { /* Send the total number of logical blocks in the current LUN */ Endpoint_Write_DWord_BE(LUN_MEDIA_BLOCKS - 1); @@ -203,20 +221,24 @@ static void SCSI_Command_Read_Capacity_10(void) /* Check if the current command is being aborted by the host */ if (IsMassStoreReset) - return; + return false; /* Send the endpoint data packet to the host */ Endpoint_ClearIN(); /* Succeed the command and update the bytes transferred counter */ CommandBlock.DataTransferLength -= 8; + + return true; } /** Command processing for an issued SCSI SEND DIAGNOSTIC command. This command performs a quick check of the Dataflash ICs on the * board, and indicates if they are present and functioning correctly. Only the Self-Test portion of the diagnostic command is * supported. + * + * \return Boolean true if the command completed successfully, false otherwise. */ -static void SCSI_Command_Send_Diagnostic(void) +static bool SCSI_Command_Send_Diagnostic(void) { /* Check to see if the SELF TEST bit is not set */ if (!(CommandBlock.SCSICommandData[1] & (1 << 2))) @@ -226,7 +248,7 @@ static void SCSI_Command_Send_Diagnostic(void) SCSI_ASENSE_INVALID_FIELD_IN_CDB, SCSI_ASENSEQ_NO_QUALIFIER); - return; + return false; } /* Check to see if all attached Dataflash ICs are functional */ @@ -237,11 +259,13 @@ static void SCSI_Command_Send_Diagnostic(void) SCSI_ASENSE_NO_ADDITIONAL_INFORMATION, SCSI_ASENSEQ_NO_QUALIFIER); - return; + return false; } /* Succeed the command and update the bytes transferred counter */ CommandBlock.DataTransferLength = 0; + + return true; } /** Command processing for an issued SCSI READ (10) or WRITE (10) command. This command reads in the block start address @@ -249,8 +273,10 @@ static void SCSI_Command_Send_Diagnostic(void) * reading and writing of the data. * * \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 void SCSI_Command_ReadWrite_10(const bool IsDataRead) +static bool SCSI_Command_ReadWrite_10(const bool IsDataRead) { uint32_t BlockAddress = SwapEndian_32(*(uint32_t*)&CommandBlock.SCSICommandData[2]); uint16_t TotalBlocks = SwapEndian_16(*(uint16_t*)&CommandBlock.SCSICommandData[7]); @@ -263,7 +289,7 @@ static void SCSI_Command_ReadWrite_10(const bool IsDataRead) SCSI_ASENSE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, SCSI_ASENSEQ_NO_QUALIFIER); - return; + return false; } #if (TOTAL_LUNS > 1) @@ -279,4 +305,6 @@ static void SCSI_Command_ReadWrite_10(const bool IsDataRead) /* Update the bytes transferred counter and succeed the command */ CommandBlock.DataTransferLength -= ((uint32_t)TotalBlocks * VIRTUAL_MEMORY_BLOCK_SIZE); + + return true; } diff --git a/Demos/Device/LowLevel/MassStorage/Lib/SCSI.h b/Demos/Device/LowLevel/MassStorage/Lib/SCSI.h index 7bee2ad753..7c6d91754f 100644 --- a/Demos/Device/LowLevel/MassStorage/Lib/SCSI.h +++ b/Demos/Device/LowLevel/MassStorage/Lib/SCSI.h @@ -58,9 +58,9 @@ * \param[in] acode New SCSI additional sense key to set the additional sense code to * \param[in] aqual New SCSI additional sense key qualifier to set the additional sense qualifier code to */ - #define SCSI_SET_SENSE(key, acode, aqual) MACROS{ SenseData.SenseKey = (key); \ - SenseData.AdditionalSenseCode = (acode); \ - SenseData.AdditionalSenseQualifier = (aqual); }MACROE + #define SCSI_SET_SENSE(Key, Acode, Aqual) MACROS{ SenseData.SenseKey = (Key); \ + SenseData.AdditionalSenseCode = (Acode); \ + SenseData.AdditionalSenseQualifier = (Aqual); }MACROE /** Macro for the \ref SCSI_Command_ReadWrite_10() function, to indicate that data is to be read from the storage medium. */ #define DATA_READ true @@ -139,11 +139,11 @@ bool SCSI_DecodeSCSICommand(void); #if defined(INCLUDE_FROM_SCSI_C) - static void SCSI_Command_Inquiry(void); - static void SCSI_Command_Request_Sense(void); - static void SCSI_Command_Read_Capacity_10(void); - static void SCSI_Command_Send_Diagnostic(void); - static void SCSI_Command_ReadWrite_10(const bool IsDataRead); + static bool SCSI_Command_Inquiry(void); + static bool SCSI_Command_Request_Sense(void); + static bool SCSI_Command_Read_Capacity_10(void); + static bool SCSI_Command_Send_Diagnostic(void); + static bool SCSI_Command_ReadWrite_10(const bool IsDataRead); #endif #endif diff --git a/LUFA/DriverStubs/Dataflash.h b/LUFA/DriverStubs/Dataflash.h index 0df9ea11c0..37c8bb0fe7 100644 --- a/LUFA/DriverStubs/Dataflash.h +++ b/LUFA/DriverStubs/Dataflash.h @@ -91,7 +91,7 @@ /** Determines the currently selected dataflash chip. * * \return Mask of the currently selected Dataflash chip, either \ref DATAFLASH_NO_CHIP if no chip is selected - * or a DATAFLASH_CHIPn mask (where n is the chip number). + * or a DATAFLASH_CHIPn mask (where n is the chip number). */ static inline uint8_t Dataflash_GetSelectedChip(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT; static inline uint8_t Dataflash_GetSelectedChip(void) diff --git a/LUFA/ManPages/ChangeLog.txt b/LUFA/ManPages/ChangeLog.txt index 999959f09c..45e894d8d5 100644 --- a/LUFA/ManPages/ChangeLog.txt +++ b/LUFA/ManPages/ChangeLog.txt @@ -12,10 +12,14 @@ * depending of if the given bank size is a compile time constant, as the compiler does a better job of optimizing * with basic code * - Changed over all device demos to use a clearer algorithm for the configuring of the application's endpoints + * - Added missing DataflashManager_CheckDataflashOperation() function to the MassStorageKeyboard demo, removed redundant + * SCSI_Codes.h file as these values are part of the MassStorage Class Driver * * Fixed: * - Fixed USB_GetHIDReportItemInfo() function modifying the given report item's data when the report item does not exist * within the supplied report of a multiple report HID device + * - Fixed MassStorage based demos and projects resetting the SCSI sense values before the command is executed, leading to + * missed SCSI sense values when the host retrieves the sense key (thanks to Martin Degelsegger) * * \section Sec_ChangeLog100807 Version 100807 * New: diff --git a/Projects/Incomplete/StandaloneProgrammer/Lib/SCSI.c b/Projects/Incomplete/StandaloneProgrammer/Lib/SCSI.c index 29f97491d1..1ca22a50e8 100644 --- a/Projects/Incomplete/StandaloneProgrammer/Lib/SCSI.c +++ b/Projects/Incomplete/StandaloneProgrammer/Lib/SCSI.c @@ -86,39 +86,39 @@ SCSI_Request_Sense_Response_t SenseData = * a command failure due to a ILLEGAL REQUEST. * * \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 */ bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) { - /* Set initial sense data, before the requested command is processed */ - SCSI_SET_SENSE(SCSI_SENSE_KEY_GOOD, - SCSI_ASENSE_NO_ADDITIONAL_INFORMATION, - SCSI_ASENSEQ_NO_QUALIFIER); - + bool CommandSuccess = false; + /* Run the appropriate SCSI command hander function based on the passed command */ switch (MSInterfaceInfo->State.CommandBlock.SCSICommandData[0]) { case SCSI_CMD_INQUIRY: - SCSI_Command_Inquiry(MSInterfaceInfo); + CommandSuccess = SCSI_Command_Inquiry(MSInterfaceInfo); break; case SCSI_CMD_REQUEST_SENSE: - SCSI_Command_Request_Sense(MSInterfaceInfo); + CommandSuccess = SCSI_Command_Request_Sense(MSInterfaceInfo); break; case SCSI_CMD_READ_CAPACITY_10: - SCSI_Command_Read_Capacity_10(MSInterfaceInfo); + CommandSuccess = SCSI_Command_Read_Capacity_10(MSInterfaceInfo); break; case SCSI_CMD_SEND_DIAGNOSTIC: - SCSI_Command_Send_Diagnostic(MSInterfaceInfo); + CommandSuccess = SCSI_Command_Send_Diagnostic(MSInterfaceInfo); break; case SCSI_CMD_WRITE_10: - SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_WRITE); + CommandSuccess = SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_WRITE); break; case SCSI_CMD_READ_10: - SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_READ); + CommandSuccess = SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_READ); break; case SCSI_CMD_TEST_UNIT_READY: case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL: case SCSI_CMD_VERIFY_10: /* These commands should just succeed, no handling required */ + CommandSuccess = true; MSInterfaceInfo->State.CommandBlock.DataTransferLength = 0; break; default: @@ -129,15 +129,27 @@ bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) break; } - return (SenseData.SenseKey == SCSI_SENSE_KEY_GOOD); + /* Check if command was successfully processed */ + if (CommandSuccess) + { + SCSI_SET_SENSE(SCSI_SENSE_KEY_GOOD, + SCSI_ASENSE_NO_ADDITIONAL_INFORMATION, + SCSI_ASENSEQ_NO_QUALIFIER); + + return true; + } + + return false; } /** Command processing for an issued SCSI INQUIRY command. This command returns information about the device's features * and capabilities to the host. * * \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 void SCSI_Command_Inquiry(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 : @@ -152,7 +164,7 @@ static void SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInf SCSI_ASENSE_INVALID_FIELD_IN_CDB, SCSI_ASENSEQ_NO_QUALIFIER); - return; + return false; } Endpoint_Write_Stream_LE(&InquiryData, BytesTransferred, NO_STREAM_CALLBACK); @@ -167,14 +179,18 @@ static void SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInf /* Succeed the command and update the bytes transferred counter */ MSInterfaceInfo->State.CommandBlock.DataTransferLength -= BytesTransferred; + + return true; } /** Command processing for an issued SCSI REQUEST SENSE command. This command returns information about the last issued command, * including the error code and additional error information so that the host can determine why a command failed to complete. * * \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 void SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) +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); @@ -187,14 +203,18 @@ static void SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterf /* Succeed the command and update the bytes transferred counter */ MSInterfaceInfo->State.CommandBlock.DataTransferLength -= BytesTransferred; + + return true; } /** Command processing for an issued SCSI READ CAPACITY (10) command. This command returns information about the device's capacity * on the selected Logical Unit (drive), as a number of OS-sized blocks. * * \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 void SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) +static bool SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) { uint32_t LastBlockAddressInLUN = (VIRTUAL_MEMORY_BLOCKS - 1); uint32_t MediaBlockSize = VIRTUAL_MEMORY_BLOCK_SIZE; @@ -205,6 +225,8 @@ static void SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInt /* Succeed the command and update the bytes transferred counter */ MSInterfaceInfo->State.CommandBlock.DataTransferLength -= 8; + + return true; } /** Command processing for an issued SCSI SEND DIAGNOSTIC command. This command performs a quick check of the Dataflash ICs on the @@ -212,8 +234,10 @@ static void SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInt * supported. * * \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 void SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) +static bool SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) { /* Check to see if the SELF TEST bit is not set */ if (!(MSInterfaceInfo->State.CommandBlock.SCSICommandData[1] & (1 << 2))) @@ -223,7 +247,7 @@ static void SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInte SCSI_ASENSE_INVALID_FIELD_IN_CDB, SCSI_ASENSEQ_NO_QUALIFIER); - return; + return false; } /* Check to see if all attached Dataflash ICs are functional */ @@ -234,11 +258,13 @@ static void SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInte SCSI_ASENSE_NO_ADDITIONAL_INFORMATION, SCSI_ASENSEQ_NO_QUALIFIER); - return; + return false; } /* Succeed the command and update the bytes transferred counter */ MSInterfaceInfo->State.CommandBlock.DataTransferLength = 0; + + return true; } /** Command processing for an issued SCSI READ (10) or WRITE (10) command. This command reads in the block start address @@ -247,12 +273,20 @@ static void SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInte * * \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 void SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo, +static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo, const bool IsDataRead) { - uint32_t BlockAddress = SwapEndian_32(*(uint32_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[2]); - uint16_t TotalBlocks = SwapEndian_16(*(uint16_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[7]); + uint32_t BlockAddress; + uint16_t TotalBlocks; + + /* 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 >= VIRTUAL_MEMORY_BLOCKS) @@ -262,7 +296,7 @@ static void SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfa SCSI_ASENSE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, SCSI_ASENSEQ_NO_QUALIFIER); - return; + return false; } /* Determine if the packet is a READ (10) or WRITE (10) command, call appropriate function */ @@ -273,5 +307,7 @@ static void SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfa /* Update the bytes transferred counter and succeed the command */ MSInterfaceInfo->State.CommandBlock.DataTransferLength -= ((uint32_t)TotalBlocks * VIRTUAL_MEMORY_BLOCK_SIZE); + + return true; } #endif diff --git a/Projects/Incomplete/StandaloneProgrammer/Lib/SCSI.h b/Projects/Incomplete/StandaloneProgrammer/Lib/SCSI.h index 22c3a1d449..6932a81520 100644 --- a/Projects/Incomplete/StandaloneProgrammer/Lib/SCSI.h +++ b/Projects/Incomplete/StandaloneProgrammer/Lib/SCSI.h @@ -43,6 +43,7 @@ #include #include + #include "StandaloneProgrammer.h" #include "Descriptors.h" #include "DataflashManager.h" @@ -55,9 +56,9 @@ * \param[in] acode New SCSI additional sense key to set the additional sense code to * \param[in] aqual New SCSI additional sense key qualifier to set the additional sense qualifier code to */ - #define SCSI_SET_SENSE(key, acode, aqual) MACROS{ SenseData.SenseKey = key; \ - SenseData.AdditionalSenseCode = acode; \ - SenseData.AdditionalSenseQualifier = aqual; }MACROE + #define SCSI_SET_SENSE(Key, Acode, Aqual) MACROS{ SenseData.SenseKey = (Key); \ + SenseData.AdditionalSenseCode = (Acode); \ + SenseData.AdditionalSenseQualifier = (Aqual); }MACROE /** Macro for the \ref SCSI_Command_ReadWrite_10() function, to indicate that data is to be read from the storage medium. */ #define DATA_READ true @@ -76,12 +77,12 @@ bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo); #if defined(INCLUDE_FROM_SCSI_C) - static void SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo); - static void SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo); - static void SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo); - static void SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo); - static void SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo, - const bool IsDataRead); + static bool SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo); + static bool SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo); + static bool SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo); + 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); #endif #endif diff --git a/Projects/TempDataLogger/Lib/SCSI.c b/Projects/TempDataLogger/Lib/SCSI.c index 6923f78199..a987319572 100644 --- a/Projects/TempDataLogger/Lib/SCSI.c +++ b/Projects/TempDataLogger/Lib/SCSI.c @@ -85,39 +85,39 @@ SCSI_Request_Sense_Response_t SenseData = * a command failure due to a ILLEGAL REQUEST. * * \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 */ bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) { - /* Set initial sense data, before the requested command is processed */ - SCSI_SET_SENSE(SCSI_SENSE_KEY_GOOD, - SCSI_ASENSE_NO_ADDITIONAL_INFORMATION, - SCSI_ASENSEQ_NO_QUALIFIER); - + bool CommandSuccess = false; + /* Run the appropriate SCSI command hander function based on the passed command */ switch (MSInterfaceInfo->State.CommandBlock.SCSICommandData[0]) { case SCSI_CMD_INQUIRY: - SCSI_Command_Inquiry(MSInterfaceInfo); + CommandSuccess = SCSI_Command_Inquiry(MSInterfaceInfo); break; case SCSI_CMD_REQUEST_SENSE: - SCSI_Command_Request_Sense(MSInterfaceInfo); + CommandSuccess = SCSI_Command_Request_Sense(MSInterfaceInfo); break; case SCSI_CMD_READ_CAPACITY_10: - SCSI_Command_Read_Capacity_10(MSInterfaceInfo); + CommandSuccess = SCSI_Command_Read_Capacity_10(MSInterfaceInfo); break; case SCSI_CMD_SEND_DIAGNOSTIC: - SCSI_Command_Send_Diagnostic(MSInterfaceInfo); + CommandSuccess = SCSI_Command_Send_Diagnostic(MSInterfaceInfo); break; case SCSI_CMD_WRITE_10: - SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_WRITE); + CommandSuccess = SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_WRITE); break; case SCSI_CMD_READ_10: - SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_READ); + CommandSuccess = SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_READ); break; case SCSI_CMD_TEST_UNIT_READY: case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL: case SCSI_CMD_VERIFY_10: /* These commands should just succeed, no handling required */ + CommandSuccess = true; MSInterfaceInfo->State.CommandBlock.DataTransferLength = 0; break; default: @@ -128,15 +128,27 @@ bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) break; } - return (SenseData.SenseKey == SCSI_SENSE_KEY_GOOD); + /* Check if command was successfully processed */ + if (CommandSuccess) + { + SCSI_SET_SENSE(SCSI_SENSE_KEY_GOOD, + SCSI_ASENSE_NO_ADDITIONAL_INFORMATION, + SCSI_ASENSEQ_NO_QUALIFIER); + + return true; + } + + return false; } /** Command processing for an issued SCSI INQUIRY command. This command returns information about the device's features * and capabilities to the host. * * \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 void SCSI_Command_Inquiry(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 : @@ -151,7 +163,7 @@ static void SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInf SCSI_ASENSE_INVALID_FIELD_IN_CDB, SCSI_ASENSEQ_NO_QUALIFIER); - return; + return false; } Endpoint_Write_Stream_LE(&InquiryData, BytesTransferred, NO_STREAM_CALLBACK); @@ -166,14 +178,18 @@ static void SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInf /* Succeed the command and update the bytes transferred counter */ MSInterfaceInfo->State.CommandBlock.DataTransferLength -= BytesTransferred; + + return true; } /** Command processing for an issued SCSI REQUEST SENSE command. This command returns information about the last issued command, * including the error code and additional error information so that the host can determine why a command failed to complete. * * \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 void SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) +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); @@ -186,14 +202,18 @@ static void SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterf /* Succeed the command and update the bytes transferred counter */ MSInterfaceInfo->State.CommandBlock.DataTransferLength -= BytesTransferred; + + return true; } /** Command processing for an issued SCSI READ CAPACITY (10) command. This command returns information about the device's capacity * on the selected Logical Unit (drive), as a number of OS-sized blocks. * * \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 void SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) +static bool SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) { uint32_t LastBlockAddressInLUN = (VIRTUAL_MEMORY_BLOCKS - 1); uint32_t MediaBlockSize = VIRTUAL_MEMORY_BLOCK_SIZE; @@ -204,6 +224,8 @@ static void SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInt /* Succeed the command and update the bytes transferred counter */ MSInterfaceInfo->State.CommandBlock.DataTransferLength -= 8; + + return true; } /** Command processing for an issued SCSI SEND DIAGNOSTIC command. This command performs a quick check of the Dataflash ICs on the @@ -211,8 +233,10 @@ static void SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInt * supported. * * \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 void SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) +static bool SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) { /* Check to see if the SELF TEST bit is not set */ if (!(MSInterfaceInfo->State.CommandBlock.SCSICommandData[1] & (1 << 2))) @@ -222,7 +246,7 @@ static void SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInte SCSI_ASENSE_INVALID_FIELD_IN_CDB, SCSI_ASENSEQ_NO_QUALIFIER); - return; + return false; } /* Check to see if all attached Dataflash ICs are functional */ @@ -233,11 +257,13 @@ static void SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInte SCSI_ASENSE_NO_ADDITIONAL_INFORMATION, SCSI_ASENSEQ_NO_QUALIFIER); - return; + return false; } /* Succeed the command and update the bytes transferred counter */ MSInterfaceInfo->State.CommandBlock.DataTransferLength = 0; + + return true; } /** Command processing for an issued SCSI READ (10) or WRITE (10) command. This command reads in the block start address @@ -246,13 +272,21 @@ static void SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInte * * \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 void SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo, +static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo, const bool IsDataRead) { - uint32_t BlockAddress = SwapEndian_32(*(uint32_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[2]); - uint16_t TotalBlocks = SwapEndian_16(*(uint16_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[7]); - + uint32_t BlockAddress; + uint16_t TotalBlocks; + + /* 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 >= VIRTUAL_MEMORY_BLOCKS) { @@ -261,7 +295,7 @@ static void SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfa SCSI_ASENSE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, SCSI_ASENSEQ_NO_QUALIFIER); - return; + return false; } /* Determine if the packet is a READ (10) or WRITE (10) command, call appropriate function */ @@ -272,4 +306,6 @@ static void SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfa /* Update the bytes transferred counter and succeed the command */ MSInterfaceInfo->State.CommandBlock.DataTransferLength -= ((uint32_t)TotalBlocks * VIRTUAL_MEMORY_BLOCK_SIZE); + + return true; } diff --git a/Projects/TempDataLogger/Lib/SCSI.h b/Projects/TempDataLogger/Lib/SCSI.h index c5504b7133..5c2112b2ca 100644 --- a/Projects/TempDataLogger/Lib/SCSI.h +++ b/Projects/TempDataLogger/Lib/SCSI.h @@ -56,9 +56,9 @@ * \param[in] acode New SCSI additional sense key to set the additional sense code to * \param[in] aqual New SCSI additional sense key qualifier to set the additional sense qualifier code to */ - #define SCSI_SET_SENSE(key, acode, aqual) MACROS{ SenseData.SenseKey = (key); \ - SenseData.AdditionalSenseCode = (acode); \ - SenseData.AdditionalSenseQualifier = (aqual); }MACROE + #define SCSI_SET_SENSE(Key, Acode, Aqual) MACROS{ SenseData.SenseKey = (Key); \ + SenseData.AdditionalSenseCode = (Acode); \ + SenseData.AdditionalSenseQualifier = (Aqual); }MACROE /** Macro for the \ref SCSI_Command_ReadWrite_10() function, to indicate that data is to be read from the storage medium. */ #define DATA_READ true @@ -76,11 +76,11 @@ bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo); #if defined(INCLUDE_FROM_SCSI_C) - static void SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo); - static void SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo); - static void SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo); - static void SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo); - static void SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo, + static bool SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo); + static bool SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo); + static bool SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo); + 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); #endif diff --git a/Projects/Webserver/Lib/SCSI.c b/Projects/Webserver/Lib/SCSI.c index 8999fabb0c..a987319572 100644 --- a/Projects/Webserver/Lib/SCSI.c +++ b/Projects/Webserver/Lib/SCSI.c @@ -85,39 +85,39 @@ SCSI_Request_Sense_Response_t SenseData = * a command failure due to a ILLEGAL REQUEST. * * \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 */ bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) { - /* Set initial sense data, before the requested command is processed */ - SCSI_SET_SENSE(SCSI_SENSE_KEY_GOOD, - SCSI_ASENSE_NO_ADDITIONAL_INFORMATION, - SCSI_ASENSEQ_NO_QUALIFIER); - + bool CommandSuccess = false; + /* Run the appropriate SCSI command hander function based on the passed command */ switch (MSInterfaceInfo->State.CommandBlock.SCSICommandData[0]) { case SCSI_CMD_INQUIRY: - SCSI_Command_Inquiry(MSInterfaceInfo); + CommandSuccess = SCSI_Command_Inquiry(MSInterfaceInfo); break; case SCSI_CMD_REQUEST_SENSE: - SCSI_Command_Request_Sense(MSInterfaceInfo); + CommandSuccess = SCSI_Command_Request_Sense(MSInterfaceInfo); break; case SCSI_CMD_READ_CAPACITY_10: - SCSI_Command_Read_Capacity_10(MSInterfaceInfo); + CommandSuccess = SCSI_Command_Read_Capacity_10(MSInterfaceInfo); break; case SCSI_CMD_SEND_DIAGNOSTIC: - SCSI_Command_Send_Diagnostic(MSInterfaceInfo); + CommandSuccess = SCSI_Command_Send_Diagnostic(MSInterfaceInfo); break; case SCSI_CMD_WRITE_10: - SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_WRITE); + CommandSuccess = SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_WRITE); break; case SCSI_CMD_READ_10: - SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_READ); + CommandSuccess = SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_READ); break; case SCSI_CMD_TEST_UNIT_READY: case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL: case SCSI_CMD_VERIFY_10: /* These commands should just succeed, no handling required */ + CommandSuccess = true; MSInterfaceInfo->State.CommandBlock.DataTransferLength = 0; break; default: @@ -128,15 +128,27 @@ bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) break; } - return (SenseData.SenseKey == SCSI_SENSE_KEY_GOOD); + /* Check if command was successfully processed */ + if (CommandSuccess) + { + SCSI_SET_SENSE(SCSI_SENSE_KEY_GOOD, + SCSI_ASENSE_NO_ADDITIONAL_INFORMATION, + SCSI_ASENSEQ_NO_QUALIFIER); + + return true; + } + + return false; } /** Command processing for an issued SCSI INQUIRY command. This command returns information about the device's features * and capabilities to the host. * * \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 void SCSI_Command_Inquiry(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 : @@ -151,7 +163,7 @@ static void SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInf SCSI_ASENSE_INVALID_FIELD_IN_CDB, SCSI_ASENSEQ_NO_QUALIFIER); - return; + return false; } Endpoint_Write_Stream_LE(&InquiryData, BytesTransferred, NO_STREAM_CALLBACK); @@ -166,14 +178,18 @@ static void SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInf /* Succeed the command and update the bytes transferred counter */ MSInterfaceInfo->State.CommandBlock.DataTransferLength -= BytesTransferred; + + return true; } /** Command processing for an issued SCSI REQUEST SENSE command. This command returns information about the last issued command, * including the error code and additional error information so that the host can determine why a command failed to complete. * * \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 void SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) +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); @@ -186,14 +202,18 @@ static void SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterf /* Succeed the command and update the bytes transferred counter */ MSInterfaceInfo->State.CommandBlock.DataTransferLength -= BytesTransferred; + + return true; } /** Command processing for an issued SCSI READ CAPACITY (10) command. This command returns information about the device's capacity * on the selected Logical Unit (drive), as a number of OS-sized blocks. * * \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 void SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) +static bool SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) { uint32_t LastBlockAddressInLUN = (VIRTUAL_MEMORY_BLOCKS - 1); uint32_t MediaBlockSize = VIRTUAL_MEMORY_BLOCK_SIZE; @@ -204,6 +224,8 @@ static void SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInt /* Succeed the command and update the bytes transferred counter */ MSInterfaceInfo->State.CommandBlock.DataTransferLength -= 8; + + return true; } /** Command processing for an issued SCSI SEND DIAGNOSTIC command. This command performs a quick check of the Dataflash ICs on the @@ -211,8 +233,10 @@ static void SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInt * supported. * * \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 void SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) +static bool SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) { /* Check to see if the SELF TEST bit is not set */ if (!(MSInterfaceInfo->State.CommandBlock.SCSICommandData[1] & (1 << 2))) @@ -222,7 +246,7 @@ static void SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInte SCSI_ASENSE_INVALID_FIELD_IN_CDB, SCSI_ASENSEQ_NO_QUALIFIER); - return; + return false; } /* Check to see if all attached Dataflash ICs are functional */ @@ -233,11 +257,13 @@ static void SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInte SCSI_ASENSE_NO_ADDITIONAL_INFORMATION, SCSI_ASENSEQ_NO_QUALIFIER); - return; + return false; } /* Succeed the command and update the bytes transferred counter */ MSInterfaceInfo->State.CommandBlock.DataTransferLength = 0; + + return true; } /** Command processing for an issued SCSI READ (10) or WRITE (10) command. This command reads in the block start address @@ -246,12 +272,20 @@ static void SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInte * * \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 void SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo, +static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo, const bool IsDataRead) { - uint32_t BlockAddress = SwapEndian_32(*(uint32_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[2]); - uint16_t TotalBlocks = SwapEndian_16(*(uint16_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[7]); + uint32_t BlockAddress; + uint16_t TotalBlocks; + + /* 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 >= VIRTUAL_MEMORY_BLOCKS) @@ -261,7 +295,7 @@ static void SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfa SCSI_ASENSE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, SCSI_ASENSEQ_NO_QUALIFIER); - return; + return false; } /* Determine if the packet is a READ (10) or WRITE (10) command, call appropriate function */ @@ -272,4 +306,6 @@ static void SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfa /* Update the bytes transferred counter and succeed the command */ MSInterfaceInfo->State.CommandBlock.DataTransferLength -= ((uint32_t)TotalBlocks * VIRTUAL_MEMORY_BLOCK_SIZE); + + return true; } diff --git a/Projects/Webserver/Lib/SCSI.h b/Projects/Webserver/Lib/SCSI.h index 3171c48991..64836c4a6c 100644 --- a/Projects/Webserver/Lib/SCSI.h +++ b/Projects/Webserver/Lib/SCSI.h @@ -55,9 +55,9 @@ * \param[in] acode New SCSI additional sense key to set the additional sense code to * \param[in] aqual New SCSI additional sense key qualifier to set the additional sense qualifier code to */ - #define SCSI_SET_SENSE(key, acode, aqual) MACROS{ SenseData.SenseKey = (key); \ - SenseData.AdditionalSenseCode = (acode); \ - SenseData.AdditionalSenseQualifier = (aqual); }MACROE + #define SCSI_SET_SENSE(Key, Acode, Aqual) MACROS{ SenseData.SenseKey = (Key); \ + SenseData.AdditionalSenseCode = (Acode); \ + SenseData.AdditionalSenseQualifier = (Aqual); }MACROE /** Macro for the \ref SCSI_Command_ReadWrite_10() function, to indicate that data is to be read from the storage medium. */ #define DATA_READ true @@ -75,11 +75,11 @@ bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo); #if defined(INCLUDE_FROM_SCSI_C) - static void SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo); - static void SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo); - static void SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo); - static void SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo); - static void SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo, + static bool SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo); + static bool SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo); + static bool SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo); + 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); #endif