Condensed SCSI command functions in the LowLevel Mass Storage Host demo, to save...
authorDean Camera <dean@fourwalledcubicle.com>
Thu, 27 Aug 2009 13:12:44 +0000 (13:12 +0000)
committerDean Camera <dean@fourwalledcubicle.com>
Thu, 27 Aug 2009 13:12:44 +0000 (13:12 +0000)
Fixed issue in AVRISP project where the target RESET line was being toggled before it was tristated, causing problems synchronising to some targets (thanks to Mike Alex).

Demos/Host/ClassDriver/MassStorageHost/MassStorageHost.c
Demos/Host/LowLevel/MassStorageHost/Lib/MassStoreCommands.c
Demos/Host/LowLevel/MassStorageHost/Lib/MassStoreCommands.h
Demos/Host/LowLevel/MassStorageHost/MassStorageHost.c
Demos/Host/LowLevel/MassStorageHost/MassStorageHost.h
LUFA/Drivers/USB/Class/Host/MassStorage.c
LUFA/ManPages/ChangeLog.txt
Projects/AVRISP/Lib/V2ProtocolTarget.c

index 0155335..c9120d5 100644 (file)
@@ -84,7 +84,7 @@ int main(void)
                                if (MS_Host_ConfigurePipes(&FlashDisk_MS_Interface,\r
                                                            ConfigDescriptorSize, ConfigDescriptorData) != MS_ENUMERROR_NoError)\r
                                {\r
-                                       printf("Attached Device Not a Valid Mouse.\r\n");\r
+                                       printf("Attached Device Not a Valid Mass Storage Device.\r\n");\r
                                        LEDs_SetAllLEDs(LEDMASK_USB_ERROR);\r
                                        USB_HostState = HOST_STATE_WaitForDeviceRemoval;\r
                                        break;\r
@@ -113,6 +113,8 @@ int main(void)
                                        break;\r
                                }\r
                                \r
+                               printf("Total LUNs: %d - Using first LUN in device.\r\n", (MaxLUNIndex + 1));\r
+                               \r
                                if (MS_Host_ResetMSInterface(&FlashDisk_MS_Interface))\r
                                {\r
                                        printf("Error resetting Mass Storage interface.\r\n");\r
index d0518df..1deefbc 100644 (file)
 #include "MassStoreCommands.h"\r
 \r
 /* Globals: */\r
-/** Current CBW to send to the device. This is automatically filled by the routines\r
- *  in this file and is not externally accessible.\r
- */\r
-static CommandBlockWrapper_t  SCSICommandBlock;\r
-\r
-/** Current CSW received from the device. This is automatically filled by the routines\r
- *  in this file and is externally accessible so that the return codes may be checked.\r
- */\r
-CommandStatusWrapper_t        SCSICommandStatus;\r
-\r
 /** Current Tag value used in issued CBWs to the device. This is automatically incremented\r
- *  by the routines in this file, and is not externally accessible.\r
+ *  each time a command is sent, and is not externally accessible.\r
  */\r
-static uint32_t               MassStore_Tag = 1;\r
+static uint32_t MassStore_Tag = 1;\r
 \r
 \r
 /** Routine to send the current CBW to the device, and increment the Tag value as needed.\r
  *\r
+ *  \param[in] SCSICommandBlock  Pointer to a SCSI command block structure to send to the attached device\r
+ *  \param[in,out] BufferPtr     Pointer to a buffer for the data to send or receive to/from the device, or NULL if no data\r
+ *\r
  *  \return A value from the Pipe_Stream_RW_ErrorCodes_t enum\r
  */\r
-static uint8_t MassStore_SendCommand(void)\r
+static uint8_t MassStore_SendCommand(CommandBlockWrapper_t* SCSICommandBlock, void* BufferPtr)\r
 {\r
        uint8_t ErrorCode = PIPE_RWSTREAM_NoError;\r
 \r
-       /* Each transmission should have a unique tag value, excluding values 0 and 0xFFFFFFFF */\r
-       if (++MassStore_Tag == 0xFFFFFFFF)\r
+       /* Each transmission should have a unique tag value, increment before use */\r
+       SCSICommandBlock->Tag = ++MassStore_Tag;\r
+\r
+       /* Wrap Tag value when invalid - MS class defines tag values of 0 and 0xFFFFFFFF to be invalid */\r
+       if (MassStore_Tag == 0xFFFFFFFF)\r
          MassStore_Tag = 1;\r
 \r
        /* Select the OUT data pipe for CBW transmission */\r
@@ -84,19 +80,27 @@ static uint8_t MassStore_SendCommand(void)
        Pipe_Unfreeze();\r
 \r
        /* Write the CBW command to the OUT pipe */\r
-       if ((ErrorCode = Pipe_Write_Stream_LE(&SCSICommandBlock, sizeof(CommandBlockWrapper_t))) != PIPE_RWSTREAM_NoError)\r
+       if ((ErrorCode = Pipe_Write_Stream_LE(SCSICommandBlock, sizeof(CommandBlockWrapper_t))) != PIPE_RWSTREAM_NoError)\r
          return ErrorCode;\r
 \r
        /* Send the data in the OUT pipe to the attached device */\r
        Pipe_ClearOUT();\r
        \r
        /* Wait until command has been sent */\r
-       while(!(Pipe_IsOUTReady()));\r
+       Pipe_WaitUntilReady();\r
 \r
        /* Freeze pipe after use */\r
        Pipe_Freeze();\r
        \r
-       return PIPE_RWSTREAM_NoError;\r
+       /* Send data if any */\r
+       if ((BufferPtr != NULL) &&\r
+           ((ErrorCode = MassStore_SendReceiveData(SCSICommandBlock, BufferPtr)) != PIPE_READYWAIT_NoError))\r
+       {\r
+               Pipe_Freeze();\r
+               return ErrorCode;\r
+       }\r
+               \r
+       return ErrorCode;\r
 }\r
 \r
 /** Waits until the attached device is ready to accept data following a CBW, checking\r
@@ -170,18 +174,23 @@ static uint8_t MassStore_WaitForDataReceived(void)
 /** Sends or receives the transaction's data stage to or from the attached device, reading or\r
  *  writing to the nominated buffer.\r
  *\r
- *  \param[in,out]  BufferPtr  Pointer to the data buffer to read from or write to\r
+ *  \param[in] SCSICommandBlock  Pointer to a SCSI command block structure being sent to the attached device\r
+ *  \param[in,out]  BufferPtr    Pointer to the data buffer to read from or write to\r
  *\r
  *  \return A value from the Pipe_Stream_RW_ErrorCodes_t enum\r
  */\r
-static uint8_t MassStore_SendReceiveData(void* BufferPtr)\r
+static uint8_t MassStore_SendReceiveData(CommandBlockWrapper_t* SCSICommandBlock, void* BufferPtr)\r
 {\r
        uint8_t  ErrorCode = PIPE_RWSTREAM_NoError;\r
-       uint16_t BytesRem  = SCSICommandBlock.Header.DataTransferLength;\r
+       uint16_t BytesRem  = SCSICommandBlock->DataTransferLength;\r
 \r
        /* Check the direction of the SCSI command data stage */\r
-       if (SCSICommandBlock.Header.Flags & COMMAND_DIRECTION_DATA_IN)\r
+       if (SCSICommandBlock->Flags & COMMAND_DIRECTION_DATA_IN)\r
        {\r
+               /* Wait until the device has replied with some data */\r
+               if ((ErrorCode = MassStore_WaitForDataReceived()) != PIPE_RWSTREAM_NoError)\r
+                 return ErrorCode;\r
+       \r
                /* Select the IN data pipe for data reception */\r
                Pipe_SelectPipe(MASS_STORE_DATA_IN_PIPE);\r
                Pipe_Unfreeze();\r
@@ -221,9 +230,11 @@ static uint8_t MassStore_SendReceiveData(void* BufferPtr)
 \r
 /** Routine to receive the current CSW from the device.\r
  *\r
- *  \return A value from the Pipe_Stream_RW_ErrorCodes_t enum\r
+ *  \param[out] SCSICommandStatus  Pointer to a destination where the returned status data should be stored\r
+ *\r
+ *  \return A value from the Pipe_Stream_RW_ErrorCodes_t enum, or MASS_STORE_SCSI_COMMAND_FAILED if the SCSI command fails\r
  */\r
-static uint8_t MassStore_GetReturnedStatus(void)\r
+static uint8_t MassStore_GetReturnedStatus(CommandStatusWrapper_t* SCSICommandStatus)\r
 {\r
        uint8_t ErrorCode = PIPE_RWSTREAM_NoError;\r
 \r
@@ -236,7 +247,7 @@ static uint8_t MassStore_GetReturnedStatus(void)
        Pipe_Unfreeze();\r
        \r
        /* Load in the CSW from the attached device */\r
-       if ((ErrorCode = Pipe_Read_Stream_LE(&SCSICommandStatus, sizeof(CommandStatusWrapper_t))) != PIPE_RWSTREAM_NoError)\r
+       if ((ErrorCode = Pipe_Read_Stream_LE(SCSICommandStatus, sizeof(CommandStatusWrapper_t))) != PIPE_RWSTREAM_NoError)\r
          return ErrorCode;\r
          \r
        /* Clear the data ready for next reception */\r
@@ -245,13 +256,17 @@ static uint8_t MassStore_GetReturnedStatus(void)
        /* Freeze the IN pipe after use */\r
        Pipe_Freeze();\r
        \r
-       return PIPE_RWSTREAM_NoError;\r
+       /* Check to see if command failed */\r
+       if (SCSICommandStatus->Status != Command_Pass)\r
+         ErrorCode = MASS_STORE_SCSI_COMMAND_FAILED;\r
+       \r
+       return ErrorCode;\r
 }\r
 \r
 /** Issues a Mass Storage class specific request to reset the attached device's Mass Storage interface,\r
  *  readying the device for the next CBW.\r
  *\r
- *  \return A value from the USB_Host_SendControlErrorCodes_t enum\r
+ *  \return A value from the USB_Host_SendControlErrorCodes_t enum, or MASS_STORE_SCSI_COMMAND_FAILED if the SCSI command fails\r
  */\r
 uint8_t MassStore_MassStorageReset(void)\r
 {\r
@@ -275,7 +290,7 @@ uint8_t MassStore_MassStorageReset(void)
  *\r
  *  \param[out] MaxLUNIndex  Pointer to the location that the maximum LUN index value should be stored\r
  *\r
- *  \return A value from the USB_Host_SendControlErrorCodes_t enum\r
+ *  \return A value from the USB_Host_SendControlErrorCodes_t enum, or MASS_STORE_SCSI_COMMAND_FAILED if the SCSI command fails\r
  */\r
 uint8_t MassStore_GetMaxLUN(uint8_t* const MaxLUNIndex)\r
 {\r
@@ -311,26 +326,21 @@ uint8_t MassStore_GetMaxLUN(uint8_t* const MaxLUNIndex)
  *  \param[in] LUNIndex    Index of the LUN inside the device the command is being addressed to\r
  *  \param[out] InquiryPtr  Pointer to the inquiry data structure where the inquiry data from the device is to be stored\r
  *\r
- *  \return A value from the Pipe_Stream_RW_ErrorCodes_t enum\r
+ *  \return A value from the Pipe_Stream_RW_ErrorCodes_t enum, or MASS_STORE_SCSI_COMMAND_FAILED if the SCSI command fails\r
  */\r
-uint8_t MassStore_Inquiry(const uint8_t LUNIndex, const SCSI_Inquiry_Response_t* const InquiryPtr)\r
+uint8_t MassStore_Inquiry(const uint8_t LUNIndex, SCSI_Inquiry_Response_t* const InquiryPtr)\r
 {\r
-       uint8_t ReturnCode = PIPE_RWSTREAM_NoError;\r
+       uint8_t ErrorCode = PIPE_RWSTREAM_NoError;\r
 \r
        /* Create a CBW with a SCSI command to issue INQUIRY command */\r
-       SCSICommandBlock = (CommandBlockWrapper_t)\r
+       CommandBlockWrapper_t SCSICommandBlock = (CommandBlockWrapper_t)\r
                {\r
-                       .Header =\r
-                               {\r
-                                       .Signature          = CBW_SIGNATURE,\r
-                                       .Tag                = MassStore_Tag,\r
-                                       .DataTransferLength = sizeof(SCSI_Inquiry_Response_t),\r
-                                       .Flags              = COMMAND_DIRECTION_DATA_IN,\r
-                                       .LUN                = LUNIndex,\r
-                                       .SCSICommandLength  = 6\r
-                               },\r
-                                       \r
-                       .SCSICommandData =\r
+                       .Signature          = CBW_SIGNATURE,\r
+                       .DataTransferLength = sizeof(SCSI_Inquiry_Response_t),\r
+                       .Flags              = COMMAND_DIRECTION_DATA_IN,\r
+                       .LUN                = LUNIndex,\r
+                       .SCSICommandLength  = 6,\r
+                       .SCSICommandData    =\r
                                {\r
                                        SCSI_CMD_INQUIRY,\r
                                        0x00,                   // Reserved\r
@@ -341,31 +351,23 @@ uint8_t MassStore_Inquiry(const uint8_t LUNIndex, const SCSI_Inquiry_Response_t*
                                }\r
                };\r
        \r
-       /* Send SCSI command to the attached device */\r
-       MassStore_SendCommand();\r
+       CommandStatusWrapper_t SCSICommandStatus;\r
 \r
-       /* Wait until data received from the device */\r
-       if ((ReturnCode = MassStore_WaitForDataReceived()) != PIPE_RWSTREAM_NoError)\r
+       /* Send the command and any data to the attached device */\r
+       if ((ErrorCode = MassStore_SendCommand(&SCSICommandBlock, InquiryPtr)) != PIPE_RWSTREAM_NoError)\r
        {\r
                Pipe_Freeze();\r
-               return ReturnCode;\r
+               return ErrorCode;\r
        }\r
-\r
-       /* Read the returned sense data into the buffer */\r
-       if ((ReturnCode = MassStore_SendReceiveData((uint8_t*)InquiryPtr)) != PIPE_RWSTREAM_NoError)\r
-       {\r
-               Pipe_Freeze();\r
-               return ReturnCode;\r
-       }       \r
        \r
-       /* Read in the returned CSW from the device */\r
-       if ((ReturnCode = MassStore_GetReturnedStatus()) != PIPE_RWSTREAM_NoError)\r
+       /* Retrieve status information from the attached device */\r
+       if ((ErrorCode = MassStore_GetReturnedStatus(&SCSICommandStatus)) != PIPE_RWSTREAM_NoError)\r
        {\r
                Pipe_Freeze();\r
-               return ReturnCode;\r
+               return ErrorCode;\r
        }\r
-       \r
-       return PIPE_RWSTREAM_NoError;\r
+\r
+       return ErrorCode;\r
 }\r
 \r
 /** Issues a SCSI Request Sense command to the attached device, to determine the current SCSI sense information. This\r
@@ -374,25 +376,20 @@ uint8_t MassStore_Inquiry(const uint8_t LUNIndex, const SCSI_Inquiry_Response_t*
  *  \param[in] LUNIndex   Index of the LUN inside the device the command is being addressed to\r
  *  \param[out] SensePtr  Pointer to the sense data structure where the sense data from the device is to be stored\r
  *\r
- *  \return A value from the Pipe_Stream_RW_ErrorCodes_t enum\r
+ *  \return A value from the Pipe_Stream_RW_ErrorCodes_t enum, or MASS_STORE_SCSI_COMMAND_FAILED if the SCSI command fails\r
  */\r
-uint8_t MassStore_RequestSense(const uint8_t LUNIndex, const SCSI_Request_Sense_Response_t* const SensePtr)\r
+uint8_t MassStore_RequestSense(const uint8_t LUNIndex, SCSI_Request_Sense_Response_t* const SensePtr)\r
 {\r
-       uint8_t ReturnCode = PIPE_RWSTREAM_NoError;\r
+       uint8_t ErrorCode = PIPE_RWSTREAM_NoError;\r
 \r
        /* Create a CBW with a SCSI command to issue REQUEST SENSE command */\r
-       SCSICommandBlock = (CommandBlockWrapper_t)\r
+       CommandBlockWrapper_t SCSICommandBlock = (CommandBlockWrapper_t)\r
                {\r
-                       .Header =\r
-                               {\r
-                                       .Signature          = CBW_SIGNATURE,\r
-                                       .Tag                = MassStore_Tag,\r
-                                       .DataTransferLength = sizeof(SCSI_Request_Sense_Response_t),\r
-                                       .Flags              = COMMAND_DIRECTION_DATA_IN,\r
-                                       .LUN                = LUNIndex,\r
-                                       .SCSICommandLength  = 6\r
-                               },\r
-                                       \r
+                       .Signature          = CBW_SIGNATURE,\r
+                       .DataTransferLength = sizeof(SCSI_Request_Sense_Response_t),\r
+                       .Flags              = COMMAND_DIRECTION_DATA_IN,\r
+                       .LUN                = LUNIndex,\r
+                       .SCSICommandLength  = 6,\r
                        .SCSICommandData =\r
                                {\r
                                        SCSI_CMD_REQUEST_SENSE,\r
@@ -404,31 +401,23 @@ uint8_t MassStore_RequestSense(const uint8_t LUNIndex, const SCSI_Request_Sense_
                                }\r
                };\r
        \r
-       /* Send SCSI command to the attached device */\r
-       MassStore_SendCommand();\r
+       CommandStatusWrapper_t SCSICommandStatus;\r
 \r
-       /* Wait until data received from the device */\r
-       if ((ReturnCode = MassStore_WaitForDataReceived()) != PIPE_RWSTREAM_NoError)\r
+       /* Send the command and any data to the attached device */\r
+       if ((ErrorCode = MassStore_SendCommand(&SCSICommandBlock, SensePtr)) != PIPE_RWSTREAM_NoError)\r
        {\r
                Pipe_Freeze();\r
-               return ReturnCode;\r
+               return ErrorCode;\r
        }\r
-\r
-       /* Read the returned sense data into the buffer */\r
-       if ((ReturnCode = MassStore_SendReceiveData((uint8_t*)SensePtr)) != PIPE_RWSTREAM_NoError)\r
-       {\r
-               Pipe_Freeze();\r
-               return ReturnCode;\r
-       }       \r
        \r
-       /* Read in the returned CSW from the device */\r
-       if ((ReturnCode = MassStore_GetReturnedStatus()) != PIPE_RWSTREAM_NoError)\r
+       /* Retrieve status information from the attached device */\r
+       if ((ErrorCode = MassStore_GetReturnedStatus(&SCSICommandStatus)) != PIPE_RWSTREAM_NoError)\r
        {\r
                Pipe_Freeze();\r
-               return ReturnCode;\r
+               return ErrorCode;\r
        }\r
-       \r
-       return PIPE_RWSTREAM_NoError;\r
+\r
+       return ErrorCode;\r
 }\r
 \r
 /** Issues a SCSI Device Block Read command to the attached device, to read in one or more data blocks from the\r
@@ -440,27 +429,22 @@ uint8_t MassStore_RequestSense(const uint8_t LUNIndex, const SCSI_Request_Sense_
  *  \param[in] BlockSize     Size in bytes of each block to read\r
  *  \param[out] BufferPtr    Pointer to the buffer where the read data is to be written to\r
  *\r
- *  \return A value from the Pipe_Stream_RW_ErrorCodes_t enum\r
+ *  \return A value from the Pipe_Stream_RW_ErrorCodes_t enum, or MASS_STORE_SCSI_COMMAND_FAILED if the SCSI command fails\r
  */\r
 uint8_t MassStore_ReadDeviceBlock(const uint8_t LUNIndex, const uint32_t BlockAddress,\r
                                   const uint8_t Blocks, const uint16_t BlockSize, void* BufferPtr)\r
 {\r
-       uint8_t ReturnCode = PIPE_RWSTREAM_NoError;\r
+       uint8_t ErrorCode = PIPE_RWSTREAM_NoError;\r
 \r
        /* Create a CBW with a SCSI command to read in the given blocks from the device */\r
-       SCSICommandBlock = (CommandBlockWrapper_t)\r
+       CommandBlockWrapper_t SCSICommandBlock = (CommandBlockWrapper_t)\r
                {\r
-                       .Header =\r
-                               {\r
-                                       .Signature          = CBW_SIGNATURE,\r
-                                       .Tag                = MassStore_Tag,\r
-                                       .DataTransferLength = ((uint32_t)Blocks * BlockSize),\r
-                                       .Flags              = COMMAND_DIRECTION_DATA_IN,\r
-                                       .LUN                = LUNIndex,\r
-                                       .SCSICommandLength  = 10\r
-                               },\r
-                                       \r
-                       .SCSICommandData =\r
+                       .Signature          = CBW_SIGNATURE,\r
+                       .DataTransferLength = ((uint32_t)Blocks * BlockSize),\r
+                       .Flags              = COMMAND_DIRECTION_DATA_IN,\r
+                       .LUN                = LUNIndex,\r
+                       .SCSICommandLength  = 10,\r
+                       .SCSICommandData    =\r
                                {\r
                                        SCSI_CMD_READ_10,\r
                                        0x00,                   // Unused (control bits, all off)\r
@@ -475,31 +459,23 @@ uint8_t MassStore_ReadDeviceBlock(const uint8_t LUNIndex, const uint32_t BlockAd
                                }\r
                };\r
        \r
-       /* Send SCSI command to the attached device */\r
-       MassStore_SendCommand();\r
+       CommandStatusWrapper_t SCSICommandStatus;\r
 \r
-       /* Wait until data received from the device */\r
-       if ((ReturnCode = MassStore_WaitForDataReceived()) != PIPE_RWSTREAM_NoError)\r
+       /* Send the command and any data to the attached device */\r
+       if ((ErrorCode = MassStore_SendCommand(&SCSICommandBlock, BufferPtr)) != PIPE_RWSTREAM_NoError)\r
        {\r
                Pipe_Freeze();\r
-               return ReturnCode;\r
+               return ErrorCode;\r
        }\r
-\r
-       /* Read the returned block data into the buffer */\r
-       if ((ReturnCode = MassStore_SendReceiveData(BufferPtr)) != PIPE_RWSTREAM_NoError)\r
-       {\r
-               Pipe_Freeze();\r
-               return ReturnCode;\r
-       }       \r
        \r
-       /* Read in the returned CSW from the device */\r
-       if ((ReturnCode = MassStore_GetReturnedStatus()) != PIPE_RWSTREAM_NoError)\r
+       /* Retrieve status information from the attached device */\r
+       if ((ErrorCode = MassStore_GetReturnedStatus(&SCSICommandStatus)) != PIPE_RWSTREAM_NoError)\r
        {\r
                Pipe_Freeze();\r
-               return ReturnCode;\r
+               return ErrorCode;\r
        }\r
-       \r
-       return PIPE_RWSTREAM_NoError;\r
+\r
+       return ErrorCode;\r
 }\r
 \r
 /** Issues a SCSI Device Block Write command to the attached device, to write one or more data blocks to the\r
@@ -511,27 +487,22 @@ uint8_t MassStore_ReadDeviceBlock(const uint8_t LUNIndex, const uint32_t BlockAd
  *  \param[in] BlockSize     Size in bytes of each block to write\r
  *  \param[in] BufferPtr     Pointer to the buffer where the write data is to be sourced from\r
  *\r
- *  \return A value from the Pipe_Stream_RW_ErrorCodes_t enum\r
+ *  \return A value from the Pipe_Stream_RW_ErrorCodes_t enum, or MASS_STORE_SCSI_COMMAND_FAILED if the SCSI command fails\r
  */\r
 uint8_t MassStore_WriteDeviceBlock(const uint8_t LUNIndex, const uint32_t BlockAddress,\r
                                    const uint8_t Blocks, const uint16_t BlockSize, void* BufferPtr)\r
 {\r
-       uint8_t ReturnCode = PIPE_RWSTREAM_NoError;\r
+       uint8_t ErrorCode = PIPE_RWSTREAM_NoError;\r
 \r
        /* Create a CBW with a SCSI command to write the given blocks to the device */\r
-       SCSICommandBlock = (CommandBlockWrapper_t)\r
+       CommandBlockWrapper_t SCSICommandBlock = (CommandBlockWrapper_t)\r
                {\r
-                       .Header =\r
-                               {\r
-                                       .Signature          = CBW_SIGNATURE,\r
-                                       .Tag                = MassStore_Tag,\r
-                                       .DataTransferLength = ((uint32_t)Blocks * BlockSize),\r
-                                       .Flags              = COMMAND_DIRECTION_DATA_OUT,\r
-                                       .LUN                = LUNIndex,\r
-                                       .SCSICommandLength  = 10\r
-                               },\r
-                                       \r
-                       .SCSICommandData =\r
+                       .Signature          = CBW_SIGNATURE,\r
+                       .DataTransferLength = ((uint32_t)Blocks * BlockSize),\r
+                       .Flags              = COMMAND_DIRECTION_DATA_OUT,\r
+                       .LUN                = LUNIndex,\r
+                       .SCSICommandLength  = 10,\r
+                       .SCSICommandData    =\r
                                {\r
                                        SCSI_CMD_WRITE_10,\r
                                        0x00,                   // Unused (control bits, all off)\r
@@ -546,24 +517,23 @@ uint8_t MassStore_WriteDeviceBlock(const uint8_t LUNIndex, const uint32_t BlockA
                                }\r
                };\r
        \r
-       /* Send SCSI command to the attached device */\r
-       MassStore_SendCommand();\r
+       CommandStatusWrapper_t SCSICommandStatus;\r
 \r
-       /* Write the data to the device from the buffer */\r
-       if ((ReturnCode = MassStore_SendReceiveData(BufferPtr)) != PIPE_RWSTREAM_NoError)\r
+       /* Send the command and any data to the attached device */\r
+       if ((ErrorCode = MassStore_SendCommand(&SCSICommandBlock, BufferPtr)) != PIPE_RWSTREAM_NoError)\r
        {\r
                Pipe_Freeze();\r
-               return ReturnCode;\r
-       }       \r
+               return ErrorCode;\r
+       }\r
        \r
-       /* Read in the returned CSW from the device */\r
-       if ((ReturnCode = MassStore_GetReturnedStatus()) != PIPE_RWSTREAM_NoError)\r
+       /* Retrieve status information from the attached device */\r
+       if ((ErrorCode = MassStore_GetReturnedStatus(&SCSICommandStatus)) != PIPE_RWSTREAM_NoError)\r
        {\r
                Pipe_Freeze();\r
-               return ReturnCode;\r
+               return ErrorCode;\r
        }\r
-       \r
-       return PIPE_RWSTREAM_NoError;\r
+\r
+       return ErrorCode;\r
 }\r
 \r
 /** Issues a SCSI Device Test Unit Ready command to the attached device, to determine if the device is ready to accept\r
@@ -571,26 +541,21 @@ uint8_t MassStore_WriteDeviceBlock(const uint8_t LUNIndex, const uint32_t BlockA
  *\r
  *  \param[in] LUNIndex      Index of the LUN inside the device the command is being addressed to\r
  *\r
- *  \return A value from the Pipe_Stream_RW_ErrorCodes_t enum\r
+ *  \return A value from the Pipe_Stream_RW_ErrorCodes_t enum, or MASS_STORE_SCSI_COMMAND_FAILED if the SCSI command fails\r
  */\r
 uint8_t MassStore_TestUnitReady(const uint8_t LUNIndex)\r
 {\r
-       uint8_t ReturnCode = PIPE_RWSTREAM_NoError;     \r
+       uint8_t ErrorCode = PIPE_RWSTREAM_NoError;      \r
 \r
        /* Create a CBW with a SCSI command to issue TEST UNIT READY command */\r
-       SCSICommandBlock = (CommandBlockWrapper_t)\r
+       CommandBlockWrapper_t SCSICommandBlock = (CommandBlockWrapper_t)\r
                {\r
-                       .Header =\r
-                               {\r
-                                       .Signature          = CBW_SIGNATURE,\r
-                                       .Tag                = MassStore_Tag,\r
-                                       .DataTransferLength = 0,\r
-                                       .Flags              = COMMAND_DIRECTION_DATA_IN,\r
-                                       .LUN                = LUNIndex,\r
-                                       .SCSICommandLength  = 6\r
-                               },\r
-                                       \r
-                       .SCSICommandData =\r
+                       .Signature          = CBW_SIGNATURE,\r
+                       .DataTransferLength = 0,\r
+                       .Flags              = COMMAND_DIRECTION_DATA_IN,\r
+                       .LUN                = LUNIndex,\r
+                       .SCSICommandLength  = 6,\r
+                       .SCSICommandData    =\r
                                {\r
                                        SCSI_CMD_TEST_UNIT_READY,\r
                                        0x00,                   // Reserved\r
@@ -601,17 +566,23 @@ uint8_t MassStore_TestUnitReady(const uint8_t LUNIndex)
                                }\r
                };\r
        \r
-       /* Send SCSI command to the attached device */\r
-       MassStore_SendCommand();\r
+       CommandStatusWrapper_t SCSICommandStatus;\r
 \r
-       /* Read in the returned CSW from the device */\r
-       if ((ReturnCode = MassStore_GetReturnedStatus()) != PIPE_RWSTREAM_NoError)\r
+       /* Send the command and any data to the attached device */\r
+       if ((ErrorCode = MassStore_SendCommand(&SCSICommandBlock, NULL)) != PIPE_RWSTREAM_NoError)\r
        {\r
                Pipe_Freeze();\r
-               return ReturnCode;\r
+               return ErrorCode;\r
        }\r
        \r
-       return PIPE_RWSTREAM_NoError;\r
+       /* Retrieve status information from the attached device */\r
+       if ((ErrorCode = MassStore_GetReturnedStatus(&SCSICommandStatus)) != PIPE_RWSTREAM_NoError)\r
+       {\r
+               Pipe_Freeze();\r
+               return ErrorCode;\r
+       }\r
+\r
+       return ErrorCode;\r
 }\r
 \r
 /** Issues a SCSI Device Read Capacity command to the attached device, to determine the capacity of the\r
@@ -620,26 +591,21 @@ uint8_t MassStore_TestUnitReady(const uint8_t LUNIndex)
  *  \param[in] LUNIndex      Index of the LUN inside the device the command is being addressed to\r
  *  \param[out] CapacityPtr  Device capacity structure where the capacity data is to be stored\r
  *\r
- *  \return A value from the Pipe_Stream_RW_ErrorCodes_t enum\r
+ *  \return A value from the Pipe_Stream_RW_ErrorCodes_t enum, or MASS_STORE_SCSI_COMMAND_FAILED if the SCSI command fails\r
  */\r
 uint8_t MassStore_ReadCapacity(const uint8_t LUNIndex, SCSI_Capacity_t* const CapacityPtr)\r
 {\r
-       uint8_t ReturnCode = PIPE_RWSTREAM_NoError;\r
+       uint8_t ErrorCode = PIPE_RWSTREAM_NoError;\r
 \r
        /* Create a CBW with a SCSI command to issue READ CAPACITY command */\r
-       SCSICommandBlock = (CommandBlockWrapper_t)\r
+       CommandBlockWrapper_t SCSICommandBlock = (CommandBlockWrapper_t)\r
                {\r
-                       .Header =\r
-                               {\r
-                                       .Signature          = CBW_SIGNATURE,\r
-                                       .Tag                = MassStore_Tag,\r
-                                       .DataTransferLength = sizeof(SCSI_Capacity_t),\r
-                                       .Flags              = COMMAND_DIRECTION_DATA_IN,\r
-                                       .LUN                = LUNIndex,\r
-                                       .SCSICommandLength  = 10\r
-                               },\r
-                                       \r
-                       .SCSICommandData =\r
+                       .Signature          = CBW_SIGNATURE,\r
+                       .DataTransferLength = sizeof(SCSI_Capacity_t),\r
+                       .Flags              = COMMAND_DIRECTION_DATA_IN,\r
+                       .LUN                = LUNIndex,\r
+                       .SCSICommandLength  = 10,\r
+                       .SCSICommandData    =\r
                                {\r
                                        SCSI_CMD_READ_CAPACITY_10,\r
                                        0x00,                   // Reserved\r
@@ -654,35 +620,27 @@ uint8_t MassStore_ReadCapacity(const uint8_t LUNIndex, SCSI_Capacity_t* const Ca
                                }\r
                };\r
        \r
-       /* Send SCSI command to the attached device */\r
-       MassStore_SendCommand();\r
+       CommandStatusWrapper_t SCSICommandStatus;\r
 \r
-       /* Wait until data received from the device */\r
-       if ((ReturnCode = MassStore_WaitForDataReceived()) != PIPE_RWSTREAM_NoError)\r
+       /* Send the command and any data to the attached device */\r
+       if ((ErrorCode = MassStore_SendCommand(&SCSICommandBlock, CapacityPtr)) != PIPE_RWSTREAM_NoError)\r
        {\r
                Pipe_Freeze();\r
-               return ReturnCode;\r
-       }\r
-\r
-       /* Read the returned capacity data into the buffer */\r
-       if ((ReturnCode = MassStore_SendReceiveData(CapacityPtr)) != PIPE_RWSTREAM_NoError)\r
-       {\r
-               Pipe_Freeze();\r
-               return ReturnCode;\r
+               return ErrorCode;\r
        }\r
          \r
        /* Endian-correct the read data */\r
        CapacityPtr->Blocks    = SwapEndian_32(CapacityPtr->Blocks);\r
        CapacityPtr->BlockSize = SwapEndian_32(CapacityPtr->BlockSize);\r
        \r
-       /* Read in the returned CSW from the device */\r
-       if ((ReturnCode = MassStore_GetReturnedStatus()) != PIPE_RWSTREAM_NoError)\r
+       /* Retrieve status information from the attached device */\r
+       if ((ErrorCode = MassStore_GetReturnedStatus(&SCSICommandStatus)) != PIPE_RWSTREAM_NoError)\r
        {\r
                Pipe_Freeze();\r
-               return ReturnCode;\r
+               return ErrorCode;\r
        }\r
-       \r
-       return PIPE_RWSTREAM_NoError;\r
+\r
+       return ErrorCode;\r
 }\r
 \r
 /** Issues a SCSI Device Prevent/Allow Medium Removal command to the attached device, to lock the physical media from\r
@@ -692,26 +650,21 @@ uint8_t MassStore_ReadCapacity(const uint8_t LUNIndex, SCSI_Capacity_t* const Ca
  *  \param[in] LUNIndex        Index of the LUN inside the device the command is being addressed to\r
  *  \param[in] PreventRemoval  Whether or not the LUN media should be locked to prevent removal or not\r
  *\r
- *  \return A value from the Pipe_Stream_RW_ErrorCodes_t enum\r
+ *  \return A value from the Pipe_Stream_RW_ErrorCodes_t enum, or MASS_STORE_SCSI_COMMAND_FAILED if the SCSI command fails\r
  */\r
 uint8_t MassStore_PreventAllowMediumRemoval(const uint8_t LUNIndex, const bool PreventRemoval)\r
 {\r
-       uint8_t ReturnCode = PIPE_RWSTREAM_NoError;\r
+       uint8_t ErrorCode = PIPE_RWSTREAM_NoError;\r
 \r
        /* Create a CBW with a SCSI command to issue PREVENT ALLOW MEDIUM REMOVAL command */\r
-       SCSICommandBlock = (CommandBlockWrapper_t)\r
+       CommandBlockWrapper_t SCSICommandBlock = (CommandBlockWrapper_t)\r
                {\r
-                       .Header =\r
-                               {\r
-                                       .Signature          = CBW_SIGNATURE,\r
-                                       .Tag                = MassStore_Tag,\r
-                                       .DataTransferLength = 0,\r
-                                       .Flags              = COMMAND_DIRECTION_DATA_OUT,\r
-                                       .LUN                = LUNIndex,\r
-                                       .SCSICommandLength  = 6\r
-                               },\r
-                                       \r
-                       .SCSICommandData =\r
+                       .Signature          = CBW_SIGNATURE,\r
+                       .DataTransferLength = 0,\r
+                       .Flags              = COMMAND_DIRECTION_DATA_OUT,\r
+                       .LUN                = LUNIndex,\r
+                       .SCSICommandLength  = 6,\r
+                       .SCSICommandData    =\r
                                {\r
                                        SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL,\r
                                        0x00,                   // Reserved\r
@@ -722,15 +675,21 @@ uint8_t MassStore_PreventAllowMediumRemoval(const uint8_t LUNIndex, const bool P
                                }\r
                };\r
        \r
-       /* Send SCSI command to the attached device */\r
-       MassStore_SendCommand();\r
+       CommandStatusWrapper_t SCSICommandStatus;\r
 \r
-       /* Read in the returned CSW from the device */\r
-       if ((ReturnCode = MassStore_GetReturnedStatus()))\r
+       /* Send the command and any data to the attached device */\r
+       if ((ErrorCode = MassStore_SendCommand(&SCSICommandBlock, NULL)) != PIPE_RWSTREAM_NoError)\r
        {\r
                Pipe_Freeze();\r
-               return ReturnCode;\r
+               return ErrorCode;\r
        }\r
        \r
-       return PIPE_RWSTREAM_NoError;\r
+       /* Retrieve status information from the attached device */\r
+       if ((ErrorCode = MassStore_GetReturnedStatus(&SCSICommandStatus)) != PIPE_RWSTREAM_NoError)\r
+       {\r
+               Pipe_Freeze();\r
+               return ErrorCode;\r
+       }\r
+\r
+       return ErrorCode;\r
 }\r
index f13b4b1..1a2e10d 100644 (file)
 \r
        /* Macros: */\r
                /** Class specific request to reset the Mass Storage interface of the attached device */\r
-               #define REQ_MassStorageReset             0xFF\r
+               #define REQ_MassStorageReset                0xFF\r
 \r
                /** Class specific request to retrieve the maximum Logical Unit Number (LUN) index of the attached device */\r
-               #define REQ_GetMaxLUN                    0xFE\r
+               #define REQ_GetMaxLUN                       0xFE\r
 \r
                /** Command Block Wrapper signature byte, for verification of valid CBW blocks */\r
-               #define CBW_SIGNATURE                    0x43425355UL\r
+               #define CBW_SIGNATURE                       0x43425355UL\r
 \r
                /** Command Static Wrapper signature byte, for verification of valid CSW blocks */\r
-               #define CSW_SIGNATURE                    0x53425355UL\r
+               #define CSW_SIGNATURE                       0x53425355UL\r
                \r
                /** Data direction mask for the Flags field of a CBW, indicating Host-to-Device transfer direction */\r
-               #define COMMAND_DIRECTION_DATA_OUT       (0 << 7)\r
+               #define COMMAND_DIRECTION_DATA_OUT          (0 << 7)\r
 \r
                /** Data direction mask for the Flags field of a CBW, indicating Device-to-Host transfer direction */\r
-               #define COMMAND_DIRECTION_DATA_IN        (1 << 7)\r
+               #define COMMAND_DIRECTION_DATA_IN           (1 << 7)\r
                \r
                /** Timeout period between the issuing of a CBW to a device, and the reception of the first packet */\r
-               #define COMMAND_DATA_TIMEOUT_MS          2000\r
+               #define COMMAND_DATA_TIMEOUT_MS             2000\r
 \r
                /** Pipe number of the Mass Storage data IN pipe */\r
-               #define MASS_STORE_DATA_IN_PIPE          1\r
+               #define MASS_STORE_DATA_IN_PIPE             1\r
 \r
                /** Pipe number of the Mass Storage data OUT pipe */\r
-               #define MASS_STORE_DATA_OUT_PIPE         2\r
+               #define MASS_STORE_DATA_OUT_PIPE            2\r
+               \r
+               /** Additional error code for Mass Storage functions when a device returns a logical command failure */\r
+               #define MASS_STORE_SCSI_COMMAND_FAILED      0xC0\r
 \r
        /* Type defines: */\r
                /** Type define for a Mass Storage class Command Block Wrapper, used to wrap SCSI\r
                 */\r
                typedef struct\r
                {\r
-                       struct\r
-                       {\r
-                               uint32_t Signature; /**< Command block signature, always equal to CBW_SIGNATURE */\r
-                               uint32_t Tag; /**< Current CBW tag, to positively associate a CBW with a CSW */\r
-                               uint32_t DataTransferLength; /**< Length of data to transfer, following the CBW */\r
-                               uint8_t  Flags; /**< Block flags, equal to one of the COMMAND_DIRECTION_DATA_* macros */\r
-                               uint8_t  LUN; /**< Logical Unit Number the CBW is addressed to in the device */\r
-                               uint8_t  SCSICommandLength; /**< Length of the SCSI command in the CBW */\r
-                       } Header;\r
-                       \r
-                       uint8_t SCSICommandData[16]; /**< SCSI command to issue to the device */\r
+                       uint32_t Signature; /**< Command block signature, always equal to CBW_SIGNATURE */\r
+                       uint32_t Tag; /**< Current CBW tag, to positively associate a CBW with a CSW (filled automatically) */\r
+                       uint32_t DataTransferLength; /**< Length of data to transfer, following the CBW */\r
+                       uint8_t  Flags; /**< Block flags, equal to one of the COMMAND_DIRECTION_DATA_* macros */\r
+                       uint8_t  LUN; /**< Logical Unit Number the CBW is addressed to in the device */\r
+                       uint8_t  SCSICommandLength; /**< Length of the SCSI command in the CBW */\r
+                       uint8_t  SCSICommandData[16]; /**< SCSI command to issue to the device */\r
                } CommandBlockWrapper_t;\r
                \r
                /** Type define for a Mass Storage class Command Status Wrapper, used to wrap SCSI\r
                        Command_Fail = 1, /**< Command failed to complete successfully */\r
                        Phase_Error  = 2 /**< Phase error while processing the issued command */\r
                };\r
-               \r
-       /* External Variables: */\r
-               extern CommandStatusWrapper_t SCSICommandStatus;\r
-               \r
+       \r
        /* Function Prototypes: */\r
                #if defined(INCLUDE_FROM_MASSSTORE_COMMANDS_C)\r
-                       static uint8_t MassStore_SendCommand(void);\r
+                       static uint8_t MassStore_SendCommand(CommandBlockWrapper_t* SCSICommandBlock, void* BufferPtr);\r
                        static uint8_t MassStore_WaitForDataReceived(void);\r
-                       static uint8_t MassStore_SendReceiveData(void* BufferPtr) ATTR_NON_NULL_PTR_ARG(1);\r
-                       static uint8_t MassStore_GetReturnedStatus(void);\r
+                       static uint8_t MassStore_SendReceiveData(CommandBlockWrapper_t* SCSICommandBlock, void* BufferPtr) ATTR_NON_NULL_PTR_ARG(1);\r
+                       static uint8_t MassStore_GetReturnedStatus(CommandStatusWrapper_t* SCSICommandStatus) ATTR_NON_NULL_PTR_ARG(1);\r
                #endif\r
                \r
                uint8_t MassStore_MassStorageReset(void);\r
                uint8_t MassStore_GetMaxLUN(uint8_t* const MaxLUNIndex);\r
-               uint8_t MassStore_RequestSense(const uint8_t LUNIndex, const SCSI_Request_Sense_Response_t* const SensePtr)\r
+               uint8_t MassStore_RequestSense(const uint8_t LUNIndex, SCSI_Request_Sense_Response_t* const SensePtr)\r
                                               ATTR_NON_NULL_PTR_ARG(2);\r
-               uint8_t MassStore_Inquiry(const uint8_t LUNIndex, const SCSI_Inquiry_Response_t* const InquiryPtr)\r
+               uint8_t MassStore_Inquiry(const uint8_t LUNIndex, SCSI_Inquiry_Response_t* const InquiryPtr)\r
                                               ATTR_NON_NULL_PTR_ARG(2);\r
                uint8_t MassStore_ReadDeviceBlock(const uint8_t LUNIndex, const uint32_t BlockAddress,\r
                                                  const uint8_t Blocks, const uint16_t BlockSize, void* BufferPtr) ATTR_NON_NULL_PTR_ARG(5);\r
index 2b27b12..855ce8d 100644 (file)
@@ -182,7 +182,7 @@ void MassStorage_Task(void)
                        /* Send the request, display error and wait for device detach if request fails */\r
                        if ((ErrorCode = MassStore_GetMaxLUN(&MassStore_MaxLUNIndex)) != HOST_SENDCONTROL_Successful)\r
                        {       \r
-                               ShowDiskReadError(PSTR("Get Max LUN"), false, ErrorCode);\r
+                               ShowDiskReadError(PSTR("Get Max LUN"), ErrorCode);\r
 \r
                                USB_HostState = HOST_STATE_WaitForDeviceRemoval;\r
                                break;\r
@@ -194,7 +194,7 @@ void MassStorage_Task(void)
                        /* Reset the Mass Storage device interface, ready for use */\r
                        if ((ErrorCode = MassStore_MassStorageReset()) != HOST_SENDCONTROL_Successful)\r
                        {\r
-                               ShowDiskReadError(PSTR("Mass Storage Reset"), false, ErrorCode);\r
+                               ShowDiskReadError(PSTR("Mass Storage Reset"), ErrorCode);\r
                                \r
                                USB_HostState = HOST_STATE_WaitForDeviceRemoval;\r
                                break;\r
@@ -203,16 +203,17 @@ void MassStorage_Task(void)
                        /* Get sense data from the device - many devices will not accept any other commands until the sense data\r
                         * is read - both on start-up and after a failed command */\r
                        SCSI_Request_Sense_Response_t SenseData;\r
-                       if (((ErrorCode = MassStore_RequestSense(0, &SenseData)) != 0) || (SCSICommandStatus.Status != Command_Pass))\r
+                       if ((ErrorCode = MassStore_RequestSense(0, &SenseData)) != 0)\r
                        {\r
-                               ShowDiskReadError(PSTR("Request Sense"), (SCSICommandStatus.Status != Command_Pass), ErrorCode);\r
+                               ShowDiskReadError(PSTR("Request Sense"), ErrorCode);\r
+                               USB_HostState = HOST_STATE_WaitForDeviceRemoval;\r
                                break;\r
                        }\r
                        \r
                        /* Set the prevent removal flag for the device, allowing it to be accessed */\r
-                       if (((ErrorCode = MassStore_PreventAllowMediumRemoval(0, true)) != 0) || (SCSICommandStatus.Status != Command_Pass))\r
+                       if ((ErrorCode = MassStore_PreventAllowMediumRemoval(0, true)) != 0)\r
                        {\r
-                               ShowDiskReadError(PSTR("Prevent/Allow Medium Removal"), (SCSICommandStatus.Status != Command_Pass), ErrorCode);\r
+                               ShowDiskReadError(PSTR("Prevent/Allow Medium Removal"), ErrorCode);\r
                                \r
                                USB_HostState = HOST_STATE_WaitForDeviceRemoval;\r
                                break;\r
@@ -220,9 +221,9 @@ void MassStorage_Task(void)
 \r
                        /* Get inquiry data from the device */\r
                        SCSI_Inquiry_Response_t InquiryData;\r
-                       if (((ErrorCode = MassStore_Inquiry(0, &InquiryData)) != 0) || (SCSICommandStatus.Status != Command_Pass))\r
+                       if ((ErrorCode = MassStore_Inquiry(0, &InquiryData)) != 0)\r
                        {\r
-                               ShowDiskReadError(PSTR("Inquiry"), (SCSICommandStatus.Status != Command_Pass), ErrorCode);\r
+                               ShowDiskReadError(PSTR("Inquiry"), ErrorCode);\r
                                \r
                                USB_HostState = HOST_STATE_WaitForDeviceRemoval;\r
                                break;\r
@@ -234,23 +235,30 @@ void MassStorage_Task(void)
                        /* Wait until disk ready */\r
                        puts_P(PSTR("Waiting until ready.."));\r
 \r
-                       do\r
+                       for (;;)\r
                        {\r
                                Serial_TxByte('.');\r
-                               \r
+\r
                                /* Abort if device removed */\r
                                if (USB_HostState == HOST_STATE_Unattached)\r
                                  break;\r
 \r
-                               if ((ErrorCode = MassStore_TestUnitReady(0)) != PIPE_RWSTREAM_NoError)\r
+                               /* Check to see if the attached device is ready for new commands */\r
+                               ErrorCode = MassStore_TestUnitReady(0);\r
+                                 \r
+                               /* If attached device is ready, abort the loop */\r
+                               if (!(ErrorCode))\r
+                                 break;\r
+\r
+                               /* If an error othe than a logical command failure (indicating device busy) returned, abort */\r
+                               if (ErrorCode != MASS_STORE_SCSI_COMMAND_FAILED)\r
                                {\r
-                                       ShowDiskReadError(PSTR("Test Unit Ready"), false, ErrorCode);\r
+                                       ShowDiskReadError(PSTR("Test Unit Ready"), ErrorCode);\r
 \r
                                        USB_HostState = HOST_STATE_WaitForDeviceRemoval;\r
                                        break;\r
                                }\r
                        }\r
-                       while (SCSICommandStatus.Status != Command_Pass);\r
 \r
                        puts_P(PSTR("\r\nRetrieving Capacity... "));\r
 \r
@@ -258,9 +266,9 @@ void MassStorage_Task(void)
                        SCSI_Capacity_t DiskCapacity;\r
 \r
                        /* Retrieve disk capacity */\r
-                       if (((ErrorCode = MassStore_ReadCapacity(0, &DiskCapacity)) != 0) || (SCSICommandStatus.Status != Command_Pass))\r
+                       if ((ErrorCode = MassStore_ReadCapacity(0, &DiskCapacity)) != 0)\r
                        {\r
-                               ShowDiskReadError(PSTR("Read Capacity"), (SCSICommandStatus.Status != Command_Pass), ErrorCode);\r
+                               ShowDiskReadError(PSTR("Read Capacity"), ErrorCode);\r
                                \r
                                USB_HostState = HOST_STATE_WaitForDeviceRemoval;\r
                                break;\r
@@ -273,10 +281,9 @@ void MassStorage_Task(void)
                        uint8_t BlockBuffer[DiskCapacity.BlockSize];\r
 \r
                        /* Read in the first 512 byte block from the device */\r
-                       if (((ErrorCode = MassStore_ReadDeviceBlock(0, 0x00000000, 1, DiskCapacity.BlockSize, BlockBuffer)) != 0) ||\r
-                           (SCSICommandStatus.Status != Command_Pass))\r
+                       if ((ErrorCode = MassStore_ReadDeviceBlock(0, 0x00000000, 1, DiskCapacity.BlockSize, BlockBuffer)) != 0)\r
                        {\r
-                               ShowDiskReadError(PSTR("Read Device Block"), (SCSICommandStatus.Status != Command_Pass), ErrorCode);\r
+                               ShowDiskReadError(PSTR("Read Device Block"), ErrorCode);\r
                                \r
                                USB_HostState = HOST_STATE_WaitForDeviceRemoval;\r
                                break;\r
@@ -320,15 +327,18 @@ void MassStorage_Task(void)
                                if (USB_HostState == HOST_STATE_Unattached)\r
                                  break;\r
                        }\r
+\r
+                       /* Abort if device removed */\r
+                       if (USB_HostState == HOST_STATE_Unattached)\r
+                         break;\r
                        \r
                        /* Print out the entire disk contents in ASCII format */\r
-                       for (uint32_t CurrBlock = 0; CurrBlock < DiskCapacity.Blocks; CurrBlock++)\r
+                       for (uint32_t CurrBlockAddress = 0; CurrBlockAddress < DiskCapacity.Blocks; CurrBlockAddress++)\r
                        {\r
                                /* Read in the next block of data from the device */\r
-                               if (((ErrorCode = MassStore_ReadDeviceBlock(0, CurrBlock, 1, DiskCapacity.BlockSize, BlockBuffer)) != 0) ||\r
-                                   (SCSICommandStatus.Status != Command_Pass))\r
+                               if ((ErrorCode = MassStore_ReadDeviceBlock(0, CurrBlockAddress, 1, DiskCapacity.BlockSize, BlockBuffer)) != 0)\r
                                {\r
-                                       ShowDiskReadError(PSTR("Read Device Block"), (SCSICommandStatus.Status != Command_Pass), ErrorCode);\r
+                                       ShowDiskReadError(PSTR("Read Device Block"), ErrorCode);\r
                                        \r
                                        USB_HostState = HOST_STATE_WaitForDeviceRemoval;\r
                                        break;\r
@@ -360,17 +370,15 @@ void MassStorage_Task(void)
  *  printing error codes to the serial port and waiting until the device is removed before\r
  *  continuing.\r
  *\r
- *  \param[in] CommandString      ASCII string located in PROGMEM space indicating what operation failed\r
- *  \param[in] FailedAtSCSILayer  Indicates if the command failed at the (logical) SCSI layer or at the physical USB layer\r
- *  \param[in] ErrorCode          Error code of the function which failed to complete successfully\r
+ *  \param[in] CommandString  ASCII string located in PROGMEM space indicating what operation failed\r
+ *  \param[in] ErrorCode      Error code of the function which failed to complete successfully\r
  */\r
-void ShowDiskReadError(char* CommandString, bool FailedAtSCSILayer, uint8_t ErrorCode)\r
+void ShowDiskReadError(char* CommandString, uint8_t ErrorCode)\r
 {\r
-       if (FailedAtSCSILayer)\r
+       if (ErrorCode == MASS_STORE_SCSI_COMMAND_FAILED)\r
        {\r
                /* Display the error code */\r
                printf_P(PSTR(ESC_FG_RED "SCSI command error (%S).\r\n"), CommandString);\r
-               printf_P(PSTR("  -- Status Code: %d" ESC_FG_WHITE), ErrorCode);\r
        }\r
        else\r
        {\r
index c071099..e9f0278 100644 (file)
@@ -82,6 +82,6 @@
                void EVENT_USB_Host_DeviceEnumerationFailed(const uint8_t ErrorCode, const uint8_t SubErrorCode);\r
                void EVENT_USB_Host_DeviceEnumerationComplete(void);\r
 \r
-               void ShowDiskReadError(char* CommandString, bool FailedAtSCSILayer, uint8_t ErrorCode);\r
+               void ShowDiskReadError(char* CommandString, uint8_t ErrorCode);\r
 \r
 #endif\r
index ba281cf..65c49b1 100644 (file)
@@ -110,8 +110,10 @@ static uint8_t DComp_NextInterfaceBulkDataEndpoint(void* CurrentDescriptor)
 {\r
        if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Endpoint)\r
        {\r
-               uint8_t EndpointType = (DESCRIPTOR_CAST(CurrentDescriptor,\r
-                                                       USB_Descriptor_Endpoint_t).Attributes & EP_TYPE_MASK);\r
+               USB_Descriptor_Endpoint_t* CurrentEndpoint = DESCRIPTOR_PCAST(CurrentDescriptor,\r
+                                                                             USB_Descriptor_Endpoint_t);\r
+\r
+               uint8_t EndpointType = (CurrentEndpoint->Attributes & EP_TYPE_MASK);\r
 \r
                if ((EndpointType == EP_TYPE_BULK) &&\r
                    (!(Pipe_IsEndpointBound(CurrentEndpoint->EndpointAddress))))\r
@@ -137,7 +139,7 @@ static uint8_t MS_Host_SendCommand(USB_ClassInfo_MS_Host_t* MSInterfaceInfo, MS_
 {\r
        uint8_t ErrorCode = PIPE_RWSTREAM_NoError;\r
 \r
-       SCSICommandBlock->Tag = MSInterfaceInfo->State.TransactionTag++;\r
+       SCSICommandBlock->Tag = ++MSInterfaceInfo->State.TransactionTag;\r
 \r
        if (MSInterfaceInfo->State.TransactionTag == 0xFFFFFFFF)\r
          MSInterfaceInfo->State.TransactionTag = 1;\r
index 261ca4e..13cf672 100644 (file)
@@ -28,6 +28,7 @@
   *  - Added non-null function parameter pointer restrictions to USB Class drivers to improve user code reliability\r
   *  - Added new "Common" section to the class drivers, to hold all mode-independant definitions for clarity\r
   *  - Moved SCSI command/sense constants into the Mass Storage Class driver, instead of the user-code\r
+  *  - Altered the SCSI commands in the LowLevel Mass Storage Host to save on FLASH space by reducing function calls\r
   *\r
   *  <b>Fixed:</b>\r
   *  - Fixed possible lockup in the CDC device class driver, when the host sends data that is a multiple of the\r
index c36295e..d06f065 100644 (file)
@@ -92,8 +92,8 @@ void V2Protocol_ChangeTargetResetLine(bool ResetTarget)
        }\r
        else\r
        {\r
-               RESET_LINE_PORT &= ~RESET_LINE_MASK;\r
                RESET_LINE_DDR  &= ~RESET_LINE_MASK;\r
+               RESET_LINE_PORT &= ~RESET_LINE_MASK;\r
        }\r
 }\r
 \r