Documentation: Update copyrights to 2019.
[pub/USBasp.git] / Bootloaders / MassStorage / Lib / SCSI.c
index 154fe48..2109bd2 100644 (file)
@@ -1,13 +1,13 @@
 /*
              LUFA Library
 /*
              LUFA Library
-     Copyright (C) Dean Camera, 2013.
+     Copyright (C) Dean Camera, 2019.
 
   dean [at] fourwalledcubicle [dot] com
            www.lufa-lib.org
 */
 
 /*
 
   dean [at] fourwalledcubicle [dot] com
            www.lufa-lib.org
 */
 
 /*
-  Copyright 2013  Dean Camera (dean [at] fourwalledcubicle [dot] com)
+  Copyright 2019  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
 
   Permission to use, copy, modify, distribute, and sell this
   software and its documentation for any purpose is hereby granted
@@ -86,7 +86,7 @@ static SCSI_Request_Sense_Response_t SenseData =
  *
  *  \param[in] MSInterfaceInfo  Pointer to the Mass Storage class interface structure that the command is associated with
  *
  *
  *  \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
+ *  \return Boolean \c true if the command completed successfully, \c false otherwise
  */
 bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
 {
  */
 bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
 {
@@ -104,9 +104,6 @@ bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
                case SCSI_CMD_READ_CAPACITY_10:
                        CommandSuccess = SCSI_Command_Read_Capacity_10(MSInterfaceInfo);
                        break;
                case SCSI_CMD_READ_CAPACITY_10:
                        CommandSuccess = SCSI_Command_Read_Capacity_10(MSInterfaceInfo);
                        break;
-               case SCSI_CMD_SEND_DIAGNOSTIC:
-                       CommandSuccess = SCSI_Command_Send_Diagnostic(MSInterfaceInfo);
-                       break;
                case SCSI_CMD_WRITE_10:
                        CommandSuccess = SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_WRITE);
                        break;
                case SCSI_CMD_WRITE_10:
                        CommandSuccess = SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_WRITE);
                        break;
@@ -117,6 +114,11 @@ bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
                        CommandSuccess = SCSI_Command_ModeSense_6(MSInterfaceInfo);
                        break;
                case SCSI_CMD_START_STOP_UNIT:
                        CommandSuccess = SCSI_Command_ModeSense_6(MSInterfaceInfo);
                        break;
                case SCSI_CMD_START_STOP_UNIT:
+#if !defined(NO_APP_START_ON_EJECT)
+                       /* If the user ejected the volume, signal bootloader exit at next opportunity. */
+                       RunBootloader = ((MSInterfaceInfo->State.CommandBlock.SCSICommandData[4] & 0x03) != 0x02);
+#endif
+               case SCSI_CMD_SEND_DIAGNOSTIC:
                case SCSI_CMD_TEST_UNIT_READY:
                case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
                case SCSI_CMD_VERIFY_10:
                case SCSI_CMD_TEST_UNIT_READY:
                case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
                case SCSI_CMD_VERIFY_10:
@@ -150,7 +152,7 @@ bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
  *
  *  \param[in] MSInterfaceInfo  Pointer to the Mass Storage class interface structure that the command is associated with
  *
  *
  *  \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.
+ *  \return Boolean \c true if the command completed successfully, \c false otherwise.
  */
 static bool SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
 {
  */
 static bool SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
 {
@@ -188,7 +190,7 @@ static bool SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInf
  *
  *  \param[in] MSInterfaceInfo  Pointer to the Mass Storage class interface structure that the command is associated with
  *
  *
  *  \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.
+ *  \return Boolean \c true if the command completed successfully, \c false otherwise.
  */
 static bool SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
 {
  */
 static bool SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
 {
@@ -210,15 +212,12 @@ static bool SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterf
  *
  *  \param[in] MSInterfaceInfo  Pointer to the Mass Storage class interface structure that the command is associated with
  *
  *
  *  \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.
+ *  \return Boolean \c true if the command completed successfully, \c false otherwise.
  */
 static bool 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        = SECTOR_SIZE_BYTES;
-
-       Endpoint_Write_Stream_BE(&LastBlockAddressInLUN, sizeof(LastBlockAddressInLUN), NULL);
-       Endpoint_Write_Stream_BE(&MediaBlockSize, sizeof(MediaBlockSize), NULL);
+       Endpoint_Write_32_BE(LUN_MEDIA_BLOCKS - 1);
+       Endpoint_Write_32_BE(SECTOR_SIZE_BYTES);
        Endpoint_ClearIN();
 
        /* Succeed the command and update the bytes transferred counter */
        Endpoint_ClearIN();
 
        /* Succeed the command and update the bytes transferred counter */
@@ -227,33 +226,6 @@ static bool SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInt
        return true;
 }
 
        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.
- *
- *  \param[in] MSInterfaceInfo  Pointer to the Mass Storage class interface structure that the command is associated with
- *
- *  \return Boolean true if the command completed successfully, false otherwise.
- */
-static bool SCSI_Command_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)))
-       {
-               /* Only self-test supported - update SENSE key and fail the command */
-               SCSI_SET_SENSE(SCSI_SENSE_KEY_ILLEGAL_REQUEST,
-                              SCSI_ASENSE_INVALID_FIELD_IN_CDB,
-                              SCSI_ASENSEQ_NO_QUALIFIER);
-
-               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
  *  and total number of blocks to process, then calls the appropriate low-level Dataflash routine to handle the actual
  *  reading and writing of the data.
 /** Command processing for an issued SCSI READ (10) or WRITE (10) command. This command reads in the block start address
  *  and total number of blocks to process, then calls the appropriate low-level Dataflash routine to handle the actual
  *  reading and writing of the data.
@@ -261,12 +233,12 @@ static bool 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)
  *
  *  \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.
+ *  \return Boolean \c true if the command completed successfully, \c false otherwise.
  */
 static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
                                       const bool IsDataRead)
 {
  */
 static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
                                       const bool IsDataRead)
 {
-       uint32_t BlockAddress;
+       uint16_t BlockAddress;
        uint16_t TotalBlocks;
 
        /* Load in the 32-bit block address (SCSI uses big-endian, so have to reverse the byte order) */
        uint16_t TotalBlocks;
 
        /* Load in the 32-bit block address (SCSI uses big-endian, so have to reverse the byte order) */
@@ -287,10 +259,13 @@ static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfa
        }
 
        /* Determine if the packet is a READ (10) or WRITE (10) command, call appropriate function */
        }
 
        /* Determine if the packet is a READ (10) or WRITE (10) command, call appropriate function */
-       if (IsDataRead == DATA_READ)
-         VirtualFAT_ReadBlocks(MSInterfaceInfo, BlockAddress, TotalBlocks);
-       else
-         VirtualFAT_WriteBlocks(MSInterfaceInfo, BlockAddress, TotalBlocks);
+       for (uint16_t i = 0; i < TotalBlocks; i++)
+       {
+               if (IsDataRead == DATA_READ)
+                 VirtualFAT_ReadBlock(BlockAddress + i);
+               else
+                 VirtualFAT_WriteBlock(BlockAddress + i);
+       }
 
        /* Update the bytes transferred counter and succeed the command */
        MSInterfaceInfo->State.CommandBlock.DataTransferLength -= ((uint32_t)TotalBlocks * SECTOR_SIZE_BYTES);
 
        /* Update the bytes transferred counter and succeed the command */
        MSInterfaceInfo->State.CommandBlock.DataTransferLength -= ((uint32_t)TotalBlocks * SECTOR_SIZE_BYTES);
@@ -303,7 +278,7 @@ static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfa
  *
  *  \param[in] MSInterfaceInfo  Pointer to the Mass Storage class interface structure that the command is associated with
  *
  *
  *  \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.
+ *  \return Boolean \c true if the command completed successfully, \c false otherwise.
  */
 static bool SCSI_Command_ModeSense_6(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
 {
  */
 static bool SCSI_Command_ModeSense_6(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
 {