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

📄 scsi_decoder.c

📁 at89c5131 实现 mass storage 的源码.
💻 C
📖 第 1 页 / 共 2 页
字号:
/**
 * @file scsi_decoder.c,v
 *
 * Copyright (c) 2004 Atmel.
 *
 * Please read file license.txt for copyright notice.
 *
 * @brief This file is the SCSI decoder module
 *
 * This file contains the routines to decode and to manage the SCSI commands
 *
 * @version 1.14 c5131-mass-storage-virtual-1_0_6 $Id: scsi_decoder.c,v 1.14 2005/03/25 09:53:51 lguilhau Exp $
 *
 * @todo
 * @bug
 */

//_____  I N C L U D E S ___________________________________________________

#include "config.h"
#include "scsi_decoder.h"
#include "conf\conf_usb.h"
#include "modules\control_access\ctrl_status.h"
#include "modules\control_access\ctrl_access.h"

//_____ M A C R O S ________________________________________________________


//_____ D E F I N I T I O N S ______________________________________________


_MEM_TYPE_SLOW_ U8  g_scsi_command[16];
_MEM_TYPE_SLOW_ U8  g_scsi_status;
_MEM_TYPE_FAST_ U32 g_scsi_data_remaining;

code    Byte    g_sbc_vendor_id[8]   = SBC_VENDOR_ID;
code    Byte    g_sbc_product_id[16] = SBC_PRODUCT_ID;
code    Byte    g_sbc_revision_id[4] = SBC_REVISION_ID;

extern  _MEM_TYPE_SLOW_  U8  usb_LUN;

_MEM_TYPE_SLOW_ s_scsi_sense  g_scsi_sense;


code  struct sbc_st_std_inquiry_data sbc_std_inquiry_data =
{
   /* Byte 0 : 0x00 */
   0x00,        /* DeviceType: Direct-access device */
   0,           /* PeripheralQualifier : Currently connected */
 
   /* Byte 1 : 0x80 */
   0,           /* Reserved1 */
   1,           /* RMB : Medium is removable */
 
 //  /* Byte 2 : 0x02 */
 //  0x02,        /* Version: Device compliant to ANSI X3.131:1994 */
 
   /* Byte 2 : 0x00 */
   0x00,        /* Version: Device not compliant to any standard */
 
   /* Byte 3 : 0x02 */
   2,           /* Response data format */
   0,           /* NormACA */
   0,           /* Obsolete0 */
   0,           /* AERC */
 
   /* Byte 4 : 0x1F */
   /* Byte 5 : 0x00 */
   /* Byte 6 : 0x00 */
                /* Reserved4[3] */
   {
      0x1F,     /* Additional Length (n-4) */
      0,        /* SCCS : SCC supported */
      0
   },
 
   /* Byte 7 : 0x00 */
   0,          /* SoftReset */
   0,          /* CommandQueue */
   0,          /* Reserved5 */
   0,          /* LinkedCommands */
   0,          /* Synchronous */
   0,          /* Wide16Bit */
   0,          /* Wide32Bit */
   0,          /* RelativeAddressing */
 
   /* Byte 8 - 15 : "ATMEL   " */
               /* VendorId[8] */
   SBC_VENDOR_ID,  
   /* Byte 16-31 : "AT89C5131 M.S.  " */
               /* ProductId[16] */
   SBC_PRODUCT_ID, 
   /* Byte 32-35 : "0.00" */
               /* ProductRevisionLevel[4] */
   SBC_REVISION_ID,
 
   /* Byte 36-55 : */
               /* VendorSpecific[20]; out[64 bytes] within one packet only. */
   {
      0, 0, 0, 0,
      0, 0, 0, 0,
      0, 0, 0, 0,
      0, 0, 0, 0,
      0, 0, 0, 0
   },
 
 
   0,          /* InfoUnitSupport */
   0,          /* QuickArbitSupport */
   0,          /* Clocking */
   0,          /* Reserved1 */
   0,          /* Reserved2 */
 
               /* VersionDescriptor[8] */
   {
      0, 0, 0, 0,
      0, 0, 0, 0
   },
 
 
               /* Reserved3[22] */
   {
      0, 0, 0, 0,
      0, 0, 0, 0,
      0, 0, 0, 0,
      0, 0, 0, 0,
      0, 0, 0, 0,
      0, 0
   }
};





static  void  send_informational_exceptions_page (void);
static  void  send_read_write_error_recovery_page (Byte);


//_____ D E C L A R A T I O N S ____________________________________________
/**
 * @brief SCSI decoder function
 *
 * This function read the SCSI command and launches the appropriate function
 *
 * @warning Code:.. bytes (function code length)
 *
 * @param nonr
 *
 * @return  FALSE: result KO,
 *          TRUE:  result OK
 *
 */
Bool scsi_decode_command(void)
{
   if (g_scsi_command[0] == SBC_CMD_WRITE_10)
   { 
      Scsi_start_write_action();
      sbc_write_10();
	   Scsi_stop_write_action();
      return TRUE;
   }
   if (g_scsi_command[0] == SBC_CMD_READ_10 )
   {
      Scsi_start_read_action();
      sbc_read_10();
      Scsi_stop_read_action();
      return TRUE;
   }

   switch (g_scsi_command[0])                /* check other command received */
   {
      case SBC_CMD_REQUEST_SENSE:             /* 0x03 - Mandatory */
           return sbc_request_sense();
           break;
  
      case SBC_CMD_INQUIRY:                   /* 0x12 - Mandatory */
           return sbc_inquiry();
           break;
      
      case SBC_CMD_TEST_UNIT_READY:           /* 0x00 - Mandatory */
           return sbc_test_unit_ready();
           break;
  
      case SBC_CMD_READ_CAPACITY:             /* 0x25 - Mandatory */
           return sbc_read_capacity();
           break;
  
      case SBC_CMD_MODE_SENSE_6:              /* 0x1A - Optional */
           return sbc_mode_sense_6();
           break;
  
      case SBC_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:/* 0x1E */
           return sbc_prevent_allow_medium_removal();
           break;
  
      case SBC_CMD_VERIFY_10:                 /* 0x2F - Optional */
           sbc_lun_status_is_good();
           break;
  
      case SBC_CMD_START_STOP_UNIT:           /* 0x1B - Optional */
           Sbc_send_good();
           Sbc_build_sense(SBC_SENSE_KEY_NO_SENSE, SBC_ASC_NO_ADDITIONAL_SENSE_INFORMATION, 0x00);
           break;

      case SBC_CMD_FORMAT_UNIT:               /* 0x04 - Mandatory */
  
      case SBC_CMD_MODE_SELECT_6:             /* 0x15 - Optional */
  
  
      case SBC_CMD_MODE_SENSE_10:             /* 0x5A - Optional */
  
  

      case SBC_CMD_SEND_DIAGNOSTIC:           /* 0x1D -  */
      case SBC_CMD_READ_LONG:                 /* 0x23 - Optional */
      case SBC_CMD_SYNCHRONIZE_CACHE:         /* 0x35 - Optional */
      case SBC_CMD_WRITE_BUFFER:              /* 0x3B - Optional */
      case SBC_CMD_RESERVE_10:                /* 0x56 - Mandatory */
      case SBC_CMD_RELEASE_10:                /* 0x57 - Mandatory - see chapter 7.16 - SPC 2 */
      default:
           { /* Command not supported */
              Sbc_send_failed();
              Sbc_build_sense(SBC_SENSE_KEY_ILLEGAL_REQUEST, SBC_ASC_INVALID_COMMAND_OPERATION_CODE, 0x00);
              return FALSE;
              break;
           }
   }
   return TRUE;
}


/**
 * @brief This function manages the SCSI REQUEST SENSE command (0x03)
 *
 * The SCSI Sense contains the status of the last command
 * This status is composed of 3 Bytes :
 * - sense key  (g_scsi_sense.key)
 * - additional sense code  (g_scsi_sense.asc)
 * - additional sense code qualifier  (g_scsi_sense.ascq)
 *
 * @warning Code:.. bytes (function code length)
 *
 * @param none
 *
 * @return  FALSE: result KO,
 *          TRUE:  result OK
 *
 */
Bool sbc_request_sense (void)
{
  U8  allocation_length, i;
  U8  request_sens_output[17];   /* the maximum size of request is 17 */

   allocation_length = g_scsi_command[4];  /* Allocation length */
 
  /* Initialize the request sense data */
  request_sens_output[0] = SBC_RESPONSE_CODE_SENSE; /* 70h */
  request_sens_output[1] = 0x00;                    /* Obsolete */
  request_sens_output[2] = g_scsi_sense.key;

  request_sens_output[3] = 0x00;   /* For direct access media, Information field */
  request_sens_output[4] = 0x00;   /* give the unsigned logical block */
  request_sens_output[5] = 0x00;   /* address associated with the sense key */
  request_sens_output[6] = 0x00;

  request_sens_output[7] = SBC_ADDITIONAL_SENSE_LENGTH; /* !! UFI device shall not adjust the Additional sense length to reflect truncation */
  request_sens_output[8] = SBC_COMMAND_SPECIFIC_INFORMATION_3;
  request_sens_output[9] = SBC_COMMAND_SPECIFIC_INFORMATION_2;
  request_sens_output[10] = SBC_COMMAND_SPECIFIC_INFORMATION_1;
  request_sens_output[11] = SBC_COMMAND_SPECIFIC_INFORMATION_0;

  request_sens_output[12] = g_scsi_sense.asc;
  request_sens_output[13] = g_scsi_sense.ascq;

  request_sens_output[14] = SBC_FIELD_REPLACEABLE_UNIT_CODE;
  request_sens_output[15] = SBC_SENSE_KEY_SPECIFIC_2;
  request_sens_output[16] = SBC_SENSE_KEY_SPECIFIC_1;
  request_sens_output[17] = SBC_SENSE_KEY_SPECIFIC_0;
 
  /* Send the request data */
  for( i=0 ; i<allocation_length ; i++ )
   {
    Usb_write_byte( request_sens_output[i] );
   }
  Sbc_valid_write_usb( allocation_length );
 
  sbc_lun_status_is_good();
   return TRUE;
}

/**
 * @brief This function manages the SCSI INQUIRY command (0x12)
 *
 * The SCSI Inquiry field contains information regarding parameters
 * of the target. For example:
 * - vendor identification
 * - product identification
 * - peripheral qualifier
 * - peripheral device type
 * - etc
 *
 * @warning Code:.. bytes (function code length)
 *
 * @param none
 *
 * @return  FALSE: result KO,
 *          TRUE:  result OK
 *
 */
Bool sbc_inquiry (void)
{ 
U8 CMDT_EVPD;
U8 page_code;
U8 allocation_length;
U8 i;
U8 code *ptr;
U8 status;

   CMDT_EVPD         = g_scsi_command[1] & 0x03;
   page_code         = g_scsi_command[2];
   allocation_length = g_scsi_command[4];
 
   status = TRUE;

 //  Usb_select_endpoint(EP_MS_IN);
   switch (CMDT_EVPD)                        /* CMDT and EPVD bits       */
   {
      case 0x00:                              /* CMDT and EPVD bits are 0 */
           if (page_code == 0x00)                /* PAGE or OPERATION CODE fields = 0x00? */
           {                                     /* then send standard inquiry data */
              ptr = (Byte *) &sbc_std_inquiry_data;

              if (allocation_length > sizeof (sbc_std_inquiry_data))
              {
                 allocation_length = sizeof (sbc_std_inquiry_data);
              }
              /* send data */
              for (i = 0; ((i != 8) && (allocation_length != i)); i++)
              {
                 Usb_write_byte((Byte)(*ptr));     /* write 8 first bytes of struct */
                 ptr++;
              }
              ptr = (Byte *) &g_sbc_vendor_id;
              for (i = 8; ((i != 16) && (allocation_length > i)); i++)
              {
                 Usb_write_byte((Byte)(*ptr));     /* write 8 bytes of vendor id */
                 ptr++;
              }
              ptr = (Byte *) &g_sbc_product_id;
              for (i = 16; ((i != 32) && (allocation_length > i)); i++)
              {
                 Usb_write_byte((Byte)(*ptr));     /* write 16 bytes of product id */
                 ptr++;
              }
              ptr = (Byte *) &g_sbc_revision_id;
              for (i = 32; ((i != 36) && (allocation_length > i)); i++)
              {
                 Usb_write_byte((Byte)(*ptr));     /* write 4 bytes of revision id */
                 ptr++;
              }
              ptr = ((Byte *) &sbc_std_inquiry_data) + 36;
      
              for (i = 36; ((i != 64) && (allocation_length > i)); i++)
              {
                 Usb_write_byte((Byte)(*ptr));     /* write last 64 bytes of struct */
                 ptr++;
              }
              if (allocation_length > 64)
              {
                 Sbc_valid_write_usb(64);
                 allocation_length -= 64;
                 for (i = allocation_length; i != 0 ; i--)
                 {
                    Usb_write_byte((Byte)(*ptr));   /* write last bytes of struct */
                    ptr++;
                 }
                 Sbc_valid_write_usb(allocation_length);
              }
              else
              {
                 Sbc_valid_write_usb(allocation_length);
              }
      
              sbc_lun_status_is_good();
           }
           else
           {                          /* CMDT=EVPD=0 and PAGE CODE <> 0x00 */
     //        Usb_enable_stall_handshake();
              status = FALSE;
              Sbc_send_failed();
              Sbc_build_sense(SBC_SENSE_KEY_ILLEGAL_REQUEST, SBC_ASC_INVALID_FIELD_IN_CDB, 0x00);
           }
           break;
      case 0x01:                   /* EVPD bit = 0 */
           switch (page_code)         /* Vital Product Data (VPD) Page code */
           {
  //          case SBC_VPD_DEVICE_IDENTIFICATION_PAGE:
  //            sbc_send_vpd (SBC_VPD_DEVICE_IDENTIFICATION_PAGE);
  //
  //            Sbc_build_sense(SBC_SENSE_KEY_NO_SENSE, 0x00, 0x00);
  //           break;
  
  //          case SBC_VPD_DEVICE_SUPPORTED_VITAL_PRODUCT_DATA_PAGE:
  //            sbc_send_vpd (SBC_VPD_DEVICE_SUPPORTED_VITAL_PRODUCT_DATA_PAGE);
  //            Sbc_build_sense(SBC_SENSE_KEY_NO_SENSE, 0x00, 0x00);
  //            break;
  
              default:
  //          Usb_enable_stall_handshake();
                status = FALSE;
                Sbc_send_failed();
                Sbc_build_sense(SBC_SENSE_KEY_ILLEGAL_REQUEST, SBC_ASC_INVALID_FIELD_IN_CDB, 0x00);
                break;
           }
           break;
  
      default:
  //      Usb_enable_stall_handshake();
           status = FALSE;
           Sbc_send_failed();
           Sbc_build_sense(SBC_SENSE_KEY_ILLEGAL_REQUEST, SBC_ASC_INVALID_FIELD_IN_CDB, 0x00);
           break;
   }
   return status;
}


Bool sbc_test_unit_ready(void)
{
   switch ( mem_test_unit_ready(usb_LUN) )
   {
           case CTRL_GOOD :
      sbc_lun_status_is_good();

⌨️ 快捷键说明

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