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

📄 scsi_decoder.c

📁 at89c5131 实现 mass storage 的源码.
💻 C
📖 第 1 页 / 共 2 页
字号:
      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 TRUE;
}


Bool sbc_read_capacity (void)
{
   _MEM_TYPE_SLOW_ U32 mem_size_nb_sector;

   switch ( mem_read_capacity( usb_LUN, &mem_size_nb_sector ) )
   {
      case CTRL_GOOD :
           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);
              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;
      }
   } 
   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();
      }
      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);
              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;
      }
   } 
   } 
   else
   { // No data to transfer
      sbc_lun_status_is_good();
   }
   return TRUE;
}

/**
 * @brief This function manages the SCSI MODE SENSE command (0x1A)
 *
 * 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 none
 *
 * @return  FALSE: result KO,
 *          TRUE:  result OK
 *
 */
Bool sbc_mode_sense_6 (void)
{ 
U8 page_control, page_code, dbd;
U8 allocation_length;
U8 gl_sbc_wr_protect = FALSE;

   dbd = g_scsi_command[1] & SBC_MSK_DBD;
   page_code = g_scsi_command[2];
   page_control = page_code & SBC_MSK_PAGE_CONTROL;
   page_code = page_code & SBC_MSK_PAGE_CODE;
 
   allocation_length = g_scsi_command[4];
 
 
   switch (page_code)            
   {
      case SBC_PAGE_CODE_INFORMATIONAL_EXCEPTIONS:       /* Page Code: Informational exceptions control page */
                                                          /* Mode Data Length */
           Usb_write_byte(SBC_MODE_DATA_LENGTH_INFORMATIONAL_EXCEPTIONS);
           Usb_write_byte(SBC_MEDIUM_TYPE);                  /* Device type      */
           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 */
           }
           Usb_write_byte(SBC_BLOCK_DESCRIPTOR_LENGTH);      /* Block descriptor length */
     
           send_informational_exceptions_page();
           /* build sense data */
           Sbc_build_sense(SBC_SENSE_KEY_NO_SENSE, 0x00, 0x00);
           /* ack write */
           Sbc_valid_write_usb(SBC_MODE_DATA_LENGTH_INFORMATIONAL_EXCEPTIONS + 1);
           sbc_lun_status_is_good();
           break;
  #if 0
      case SBC_PAGE_CODE_FORMAT_DEVICE:
           Usb_write_byte(SBC_MODE_DATA_LENGTH_FORMAT_DEVICE);
           Usb_write_byte(SBC_MEDIUM_TYPE);                  /* Device type      */
           Usb_write_byte(SBC_DEVICE_SPECIFIC_PARAMETER);    /* Device specific parameter */
           Usb_write_byte(SBC_BLOCK_DESCRIPTOR_LENGTH);      /* Block descriptor length */
     
           send_format_device_page();
           send_informational_exceptions_page();
           /* build sense data */
           Sbc_build_sense(SBC_SENSE_KEY_NO_SENSE, 0x00, 0x00);
           /* ack write */
           Sbc_valid_write_usb(SBC_MODE_DATA_LENGTH_FORMAT_DEVICE + 1);
           sbc_lun_status_is_good();
           break;
  #endif
      case SBC_PAGE_CODE_READ_WRITE_ERROR_RECOVERY:      
                                                             /* Mode Data Length */
           Usb_write_byte(SBC_MODE_DATA_LENGTH_READ_WRITE_ERROR_RECOVERY);
           Usb_write_byte(SBC_MEDIUM_TYPE);                  /* Device type      */
           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 */
           }
           Usb_write_byte(SBC_BLOCK_DESCRIPTOR_LENGTH);      /* Block descriptor length */
           send_read_write_error_recovery_page(allocation_length); 
           /* build sense data */
           Sbc_build_sense(SBC_SENSE_KEY_NO_SENSE, 0x00, 0x00);
           /* ack write */
           Sbc_valid_write_usb(SBC_MODE_DATA_LENGTH_READ_WRITE_ERROR_RECOVERY + 1);               
           sbc_lun_status_is_good();
           break;
  
  #if 0        
      case SBC_PAGE_CODE_FLEXIBLE_DISK:      
                                                           /* Mode Data Length */
           Usb_write_byte(SBC_MODE_DATA_LENGTH_FLEXIBLE_DISK);
           Usb_write_byte(SBC_MEDIUM_TYPE);                /* Device type */
           Usb_write_byte(SBC_DEVICE_SPECIFIC_PARAMETER);  /* Device specific parameter */
           Usb_write_byte(SBC_BLOCK_DESCRIPTOR_LENGTH);    /* Block descriptor length */
           send_flexible_disk_page(); 
           /* build sense data */
           Sbc_build_sense(SBC_SENSE_KEY_NO_SENSE, 0x00, 0x00);
           /* ack write */
           Sbc_valid_write_usb(SBC_MODE_DATA_LENGTH_FLEXIBLE_DISK + 1);               
           sbc_lun_status_is_good();
           break;
  #endif
  
      case SBC_PAGE_CODE_ALL:
           Usb_write_byte(SBC_MODE_DATA_LENGTH_CODE_ALL);  /* Mode Data Length */
           Usb_write_byte(SBC_MEDIUM_TYPE);                /* Device type */
           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 */
           }
           Usb_write_byte(SBC_BLOCK_DESCRIPTOR_LENGTH);    /* Block descriptor length */
     
           if (allocation_length == 4)
           {
              Sbc_valid_write_usb(4);
              sbc_lun_status_is_good();
              break;
           }
     
            /* send page by ascending order code */
           send_read_write_error_recovery_page(allocation_length); /* 12 bytes */
     //      send_format_device_page();                    /* 24 bytes */
           if (allocation_length > 12)
           {
     //         send_flexible_disk_page();                    /* 32 bytes */  
              send_informational_exceptions_page();         /* 12 bytes */
           }
        
           /* build sense data */
           Sbc_build_sense(SBC_SENSE_KEY_NO_SENSE, SBC_ASC_NO_ADDITIONAL_SENSE_INFORMATION, 0x00);
     
           /* ack write */
           if (allocation_length > 12)
           {
              Sbc_valid_write_usb(SBC_MODE_DATA_LENGTH_CODE_ALL + 1);               
           }
           else
           {
              Sbc_valid_write_usb(allocation_length);
           }
     
           sbc_lun_status_is_good();
           break;
  
      default:
     //      Usb_enable_stall_handshake();
//           Sbc_send_check_condition();
           Sbc_send_failed();
           Sbc_build_sense(SBC_SENSE_KEY_ILLEGAL_REQUEST, SBC_ASC_INVALID_FIELD_IN_CDB, 0x00);
           return FALSE;
           break;
   }
   return TRUE;
}

/**
 * @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 (Byte 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 + -