⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scsi_decoder.c

📁 基于at90usb1287的数据存储器例子
💻 C
📖 第 1 页 / 共 2 页
字号:
      Usb_write_byte(MSB0(mem_size_nb_sector));  // return nb block
      Usb_write_byte(MSB1(mem_size_nb_sector));
      Usb_write_byte(MSB2(mem_size_nb_sector));
      Usb_write_byte(MSB3(mem_size_nb_sector));
      Usb_write_byte( 0               );        // return block size (= 512B)
      Usb_write_byte( 0               );
      Usb_write_byte( (U8)(512 >> 8)  );
      Usb_write_byte( (U8)(512 & 0xFF));

      Sbc_valid_write_usb(SBC_READ_CAPACITY_LENGTH);
      sbc_lun_status_is_good();
      return TRUE;
      break;

   case CTRL_NO_PRESENT :
      sbc_lun_status_is_not_present();
      break;

   case CTRL_BUSY :
      sbc_lun_status_is_busy_or_change();
      break;

   case CTRL_FAIL :
   default :
      sbc_lun_status_is_fail();
      break;
   }
   return FALSE;
}


Bool sbc_read_10 (void)
{
   U32   mass_addr;                    // rd or wr block address
   U16   mass_size;                    // rd or write nb of blocks

   MSB0(mass_addr) = g_scsi_command[2];  // read address
   MSB1(mass_addr) = g_scsi_command[3];
   MSB2(mass_addr) = g_scsi_command[4];
   MSB3(mass_addr) = g_scsi_command[5];

   MSB(mass_size) = g_scsi_command[7];  // read size
   LSB(mass_size) = g_scsi_command[8];

   if (mass_size != 0)
   {
      switch ( memory_2_usb( usb_LUN , mass_addr, mass_size ) )
      {
      case CTRL_GOOD :
         sbc_lun_status_is_good();
         g_scsi_data_remaining = g_scsi_data_remaining - (512 * (Uint32)mass_size);
         return TRUE;
         break;

      case CTRL_NO_PRESENT :
         sbc_lun_status_is_not_present();
         return FALSE;
         break;

      case CTRL_BUSY :
         sbc_lun_status_is_busy_or_change();
         return FALSE;
         break;

      case CTRL_FAIL :
      default :
         sbc_lun_status_is_fail();
         return FALSE;
         break;
      }
   }
   else
   {  // No data to transfer
      sbc_lun_status_is_good();
   }
   return TRUE;
}


Bool sbc_write_10 (void)
{
   U32   mass_addr;                    // rd or wr block address
   U16   mass_size;                    // rd or write nb of blocks

   MSB0(mass_addr) = g_scsi_command[2];  // read address
   MSB1(mass_addr) = g_scsi_command[3];
   MSB2(mass_addr) = g_scsi_command[4];
   MSB3(mass_addr) = g_scsi_command[5];

   MSB(mass_size) = g_scsi_command[7];  // read size
   LSB(mass_size) = g_scsi_command[8];

   if (mass_size != 0)
   {
      if( TRUE == mem_wr_protect( usb_LUN ) )
      {
         sbc_lun_status_is_protected();
         return FALSE;
#warning For Win98 data must be read to avoid blocking
      }
      else
      {
         switch (usb_2_memory( usb_LUN , mass_addr, mass_size ))
         {
         case CTRL_GOOD :
            sbc_lun_status_is_good();
            g_scsi_data_remaining = g_scsi_data_remaining - (512 * (Uint32)mass_size);
            return TRUE;
            break;

         case CTRL_NO_PRESENT :
            sbc_lun_status_is_not_present();
            return FALSE;
            break;

         case CTRL_BUSY :
            sbc_lun_status_is_busy_or_change();
            return FALSE;
            break;

         case CTRL_FAIL :
         default :
            sbc_lun_status_is_fail();
            return FALSE;
            break;
         }
      }
   }
   else
   {  // No data to transfer
      sbc_lun_status_is_good();
   }
   return TRUE;
}


/**
 * @brief This function manages the SCSI MODE SENSE command (0x1A for sense 6 and 0x5A for sense 10)
 *
 * The SCSI mode sense function returns parameters to an application client.
 * It is a complementary command to the SCSI MODE SELECT command.
 *
 * @warning Code:.. bytes (function code length)
 *
 * @param b_sens_10 ( TRUE = sense 10, TRUE = sense 6)
 *
 * @return  FALSE: result KO,
 *          TRUE:  result OK
 *
 */
Bool sbc_mode_sense( Bool b_sense_10 )
{
   U8 allocation_length;

   if( b_sense_10 )
      allocation_length = g_scsi_command[8];
   else
      allocation_length = g_scsi_command[4];

   // switch for page code
   switch ( g_scsi_command[2] & SBC_MSK_PAGE_CODE )
   {
      case SBC_PAGE_CODE_INFORMATIONAL_EXCEPTIONS:       /* Page Code: Informational exceptions control page */
         sbc_header_mode_sense( b_sense_10 , SBC_MODE_DATA_LENGTH_INFORMATIONAL_EXCEPTIONS );
         send_informational_exceptions_page();
         Sbc_valid_write_usb(SBC_MODE_DATA_LENGTH_INFORMATIONAL_EXCEPTIONS + 1);
         break;

      case SBC_PAGE_CODE_READ_WRITE_ERROR_RECOVERY:
         sbc_header_mode_sense( b_sense_10 , SBC_MODE_DATA_LENGTH_READ_WRITE_ERROR_RECOVERY );
         send_read_write_error_recovery_page(allocation_length);
         Sbc_valid_write_usb(SBC_MODE_DATA_LENGTH_READ_WRITE_ERROR_RECOVERY + 1);
         break;

      case SBC_PAGE_CODE_ALL:
         sbc_header_mode_sense( b_sense_10 , SBC_MODE_DATA_LENGTH_CODE_ALL );
         if( b_sense_10 )
         {
            if (allocation_length == 8)
            {
               Sbc_valid_write_usb(8);
               break;
            }
         }
         else
         {
            if (allocation_length == 4)
            {
               Sbc_valid_write_usb(4);
               break;
            }
         }
         // send page by ascending order code
         send_read_write_error_recovery_page(allocation_length);  // 12 bytes
         if (allocation_length > 12)
         {
            send_informational_exceptions_page();                 // 12 bytes
            Sbc_valid_write_usb(SBC_MODE_DATA_LENGTH_CODE_ALL + 1);
         }
         else
         {
            Sbc_valid_write_usb(allocation_length);
         }
         break;

      default:
           Sbc_send_failed();
           Sbc_build_sense(SBC_SENSE_KEY_ILLEGAL_REQUEST, SBC_ASC_INVALID_FIELD_IN_CDB, 0x00);
           return FALSE;
           break;
   }
   sbc_lun_status_is_good();
   return TRUE;
}


/**
 * @brief This function send the header of the SCSI MODE SENSE command
 *
 * @param b_sens_10 ( TRUE = sense 10, FALSE = sense 6)
 * @param u8_data_length ( data length in byte )
 *
 */
void sbc_header_mode_sense( Bool b_sense_10 , U8 u8_data_length )
{
   // Send Data length
   if( b_sense_10 )
   {
      Usb_write_byte(0);
   }
   Usb_write_byte( u8_data_length );

   // Send device type
   Usb_write_byte(SBC_MEDIUM_TYPE);

   // Write protect status
   if (mem_wr_protect( usb_LUN ))
   {
      Usb_write_byte(SBC_DEV_SPEC_PARAM_WR_PROTECT);  // Device is write protected
   }
   else
   {
      Usb_write_byte(SBC_DEV_SPEC_PARAM_WR_ENABLE);   // Device is write enabled
   }

   if( b_sense_10 )
   {  // Reserved
      Usb_write_byte(0);
      Usb_write_byte(0);
   }

   // Send Block descriptor length
   if( b_sense_10 )
   {
      Usb_write_byte(0);
   }
   Usb_write_byte(SBC_BLOCK_DESCRIPTOR_LENGTH);
}


/**
 * @brief This function writes informational exceptions page parameters
 *
 * @warning Code:.. bytes (function code length)
 *
 * @param none
 *
 * @return  FALSE: result KO,
 *          TRUE:  result OK
 *
 */
void send_informational_exceptions_page (void)
{
   Usb_write_byte(SBC_PAGE_CODE_INFORMATIONAL_EXCEPTIONS);     /* Page Code: Informational exceptions control page */
                                                               /* See chapter 8.3.8 on SPC-2 specification */
   Usb_write_byte(SBC_PAGE_LENGTH_INFORMATIONAL_EXCEPTIONS);   /* Page Length */
   Usb_write_byte(0x00);                                       /* ..., Test bit = 0, ... */
   Usb_write_byte(SBC_MRIE);                                   /* MRIE = 0x05 */
   Usb_write_byte(0x00);                                       /* Interval Timer (MSB) */
   Usb_write_byte(0x00);
   Usb_write_byte(0x00);
   Usb_write_byte(0x00);                                       /* Interval Timer (LSB) */
   Usb_write_byte(0x00);                                       /* Report Count (MSB) */
   Usb_write_byte(0x00);
   Usb_write_byte(0x00);
   Usb_write_byte(0x01);                                       /* Report Count (LSB) */
}


/**
 * @brief This function writes error recovery page
 *
 * @warning Code:.. bytes (function code length)
 *
 * @param none
 *
 * @return  FALSE: result KO,
 *          TRUE:  result OK
 *
 */
void send_read_write_error_recovery_page (U8 length)
{
   Usb_write_byte(SBC_PAGE_CODE_READ_WRITE_ERROR_RECOVERY);

   Usb_write_byte(SBC_PAGE_LENGTH_READ_WRITE_ERROR_RECOVERY);   /* Page Length */
   Usb_write_byte(0x80);
   Usb_write_byte(SBC_READ_RETRY_COUNT);
   Usb_write_byte(SBC_CORRECTION_SPAN);
   Usb_write_byte(SBC_HEAD_OFFSET_COUNT);
   Usb_write_byte(SBC_DATA_STROBE_OFFSET);
   Usb_write_byte(0x00);   /* Reserved */

   if (length > 12)
   {
      Usb_write_byte(SBC_WRITE_RETRY_COUNT);
      Usb_write_byte(0x00);
      Usb_write_byte(SBC_RECOVERY_LIMIT_MSB);
      Usb_write_byte(SBC_RECOVERY_LIMIT_LSB);
   }
}

/**
 * @brief This function manages the SCSI PREVENT ALLOW MEDIUM REMOVAL
 *        command (0x1E)
 *
 * The SCSI prevent allow medium removal command requests that the target
 * enable or disable the removal of the medium in the logical unit.
 *
 * @warning Code:.. bytes (function code length)
 *
 * @param none
 *
 * @return  FALSE: result KO,
 *          TRUE:  result OK
 *
 */
Bool sbc_prevent_allow_medium_removal(void)
{
   sbc_lun_status_is_good();
   return TRUE;
}


//! This fonction send the UFI status GOOD
//!
void sbc_lun_status_is_good(void)
{
   Sbc_send_good();
   Sbc_build_sense(SBC_SENSE_KEY_NO_SENSE, SBC_ASC_NO_ADDITIONAL_SENSE_INFORMATION, 0x00);
}

//! This fonction send the UFI status "lun not present"
//!
void sbc_lun_status_is_not_present(void)
{
   Sbc_send_failed();
   Sbc_build_sense(SBC_SENSE_KEY_NOT_READY, SBC_ASC_MEDIUM_NOT_PRESENT, 0x00);
}

//! This fonction send the UFI status busy and change
//!
void sbc_lun_status_is_busy_or_change(void)
{
   Sbc_send_failed();
   Sbc_build_sense(SBC_SENSE_KEY_UNIT_ATTENTION, SBC_ASC_NOT_READY_TO_READY_CHANGE, 0x00 );
}

//! This fonction send the UFI status FAIL
//!
void sbc_lun_status_is_fail(void)
{
   Sbc_send_failed();
   Sbc_build_sense(SBC_SENSE_KEY_HARDWARE_ERROR, SBC_ASC_NO_ADDITIONAL_SENSE_INFORMATION, 0x00);
}

//! This fonction send the UFI status FAIL because write protection
//!
void sbc_lun_status_is_protected(void)
{
   Sbc_send_failed();
   Sbc_build_sense(SBC_SENSE_KEY_DATA_PROTECT, SBC_ASC_WRITE_PROTECTED, 0x00);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -