scsi_decoder.c File Reference


Detailed Description

Management of the SCSI decoding.

This file manages the SCSI decoding.

Author:
Atmel Corporation: http://www.atmel.com
Support and FAQ: http://support.atmel.no/

Definition in file scsi_decoder.c.

#include "conf_usb.h"
#include "scsi_decoder.h"
#include "usb_drv.h"
#include "ctrl_access.h"

Go to the source code of this file.

Functions

static void sbc_header_mode_sense (Bool b_sense_10, U8 u8_data_length)
 Writes the header of the MODE SENSE (6) and (10) commands.
Bool sbc_inquiry (void)
 Manages the INQUIRY command.
void sbc_lun_status_is_busy_or_change (void)
 Sends the status "busy or changed".
void sbc_lun_status_is_cdb_field (void)
 Sends the status "FAIL because CDB field is invalid".
void sbc_lun_status_is_fail (void)
 Sends the status "FAILED".
void sbc_lun_status_is_good (void)
 Sends the status "GOOD".
void sbc_lun_status_is_not_present (void)
 Sends the status "LUN not present".
void sbc_lun_status_is_protected (void)
 Sends the status "FAILED because of write protection".
Bool sbc_mode_sense (Bool b_sense_10)
 Manages the MODE SENSE (6) and (10) commands.
Bool sbc_prevent_allow_medium_removal (void)
 Manages the PREVENT ALLOW MEDIUM REMOVAL command.
Bool sbc_read_10 (void)
 Manages the READ (10) command.
Bool sbc_read_capacity (void)
 Manages the READ CAPACITY (10) command.
Bool sbc_request_sense (void)
 Manages the REQUEST SENSE command.
Bool sbc_test_unit_ready (void)
 Manages the TEST UNIT READY command.
Bool sbc_write_10 (void)
 Manages the WRITE (10) command.
Bool scsi_decode_command (void)
 Decodes and launches the execution of SCSI commands.
static void send_informational_exceptions_page (void)
 Writes the Informational Exceptions Control mode page.
static void send_read_write_error_recovery_page (U8 length)
 Writes the Error Recovery mode page.

Variables

U8 g_scsi_command [16]
 SCSI command buffer.
U32 g_scsi_data_remaining
 Remaining data transfer length.
U8 g_scsi_ep_ms_in
 USB mass-storage IN endpoint.
U8 g_scsi_ep_ms_out
 USB mass-storage OUT endpoint.
s_scsi_sense g_scsi_sense
 Sense data.
U8 g_scsi_status
 SCSI status.
U8 ms_endpoint
static const
sbc_st_std_inquiry_data 
sbc_std_inquiry_data
 INQUIRY data.
U8 usb_LUN


Function Documentation

static void sbc_header_mode_sense ( Bool  b_sense_10,
U8  u8_data_length 
) [static]

Writes the header of the MODE SENSE (6) and (10) commands.

Parameters:
b_sense_10 Boolean indicating whether the (10) version of the command is requested:
  • TRUE to specify a MODE SENSE (10) command;
  • FALSE to specify a MODE SENSE (6) command.
u8_data_length Data length in bytes.

Definition at line 591 of file scsi_decoder.c.

References g_scsi_ep_ms_in, SBC_BLOCK_DESCRIPTOR_LENGTH, SBC_DEV_SPEC_PARAM_WR_ENABLE, SBC_DEV_SPEC_PARAM_WR_PROTECT, SBC_MEDIUM_TYPE, and usb_LUN.

Referenced by sbc_mode_sense().

00592 {
00593   Usb_reset_endpoint_fifo_access(g_scsi_ep_ms_in);
00594 
00595   // Send data length.
00596   if (b_sense_10)
00597   {
00598     Usb_write_endpoint_data(g_scsi_ep_ms_in, 8, 0);
00599   }
00600   Usb_write_endpoint_data(g_scsi_ep_ms_in, 8, u8_data_length);
00601 
00602   // Send device type.
00603   Usb_write_endpoint_data(g_scsi_ep_ms_in, 8, SBC_MEDIUM_TYPE);
00604 
00605   // Write protect status.
00606   Usb_write_endpoint_data(g_scsi_ep_ms_in, 8,
00607                           (mem_wr_protect(usb_LUN)) ? SBC_DEV_SPEC_PARAM_WR_PROTECT :
00608                                                       SBC_DEV_SPEC_PARAM_WR_ENABLE);
00609 
00610   if (b_sense_10)
00611   {
00612     // Reserved.
00613     Usb_write_endpoint_data(g_scsi_ep_ms_in, 16, 0);
00614   }
00615 
00616   // Send block descriptor length.
00617   if (b_sense_10)
00618   {
00619     Usb_write_endpoint_data(g_scsi_ep_ms_in, 8, 0);
00620   }
00621   Usb_write_endpoint_data(g_scsi_ep_ms_in, 8, SBC_BLOCK_DESCRIPTOR_LENGTH);
00622 }

Bool sbc_inquiry ( void   ) 

Manages the INQUIRY command.

The INQUIRY command requests that information regarding the logical unit and SCSI target device be sent to the application client.

See sbc_st_std_inquiry_data.

Returns:
Boolean indicating success.

Definition at line 326 of file scsi_decoder.c.

References EP_MS_IN, g_scsi_command, g_scsi_ep_ms_in, sbc_lun_status_is_cdb_field(), sbc_lun_status_is_good(), and Sbc_valid_write_usb.

Referenced by scsi_decode_command().

00327 {
00328   U8 allocation_length;
00329 
00330   // CMDT or EPVD bit is not 0 or PAGE or OPERATION CODE fields != 0x00.
00331   if ((g_scsi_command[1] & 0x03) || g_scsi_command[2])
00332   {
00333     sbc_lun_status_is_cdb_field();
00334     return FALSE;
00335   }
00336   
00337   // Send standard INQUIRY data (bytes 0 to (allocation_length - 1)).
00338   allocation_length = min(g_scsi_command[4], sizeof(sbc_st_std_inquiry_data));
00339   if( allocation_length != 0 )
00340   {
00341      while (!Is_usb_in_ready(g_scsi_ep_ms_in))
00342      {
00343        if(!Is_usb_endpoint_enabled(g_scsi_ep_ms_in))
00344          return FALSE; // USB Reset
00345      }         
00346      Usb_reset_endpoint_fifo_access(g_scsi_ep_ms_in);
00347      usb_write_ep_txpacket(g_scsi_ep_ms_in, &sbc_std_inquiry_data,
00348                            allocation_length, NULL);
00349      Sbc_valid_write_usb(allocation_length);
00350      // MSC Compliance - Wait end of all transmitions on USB line, because a stall may be send after data
00351      while( 0 != Usb_nb_busy_bank(EP_MS_IN) );
00352   }
00353   sbc_lun_status_is_good();
00354   return (allocation_length == g_scsi_command[4]);
00355 }

void sbc_lun_status_is_busy_or_change ( void   ) 

void sbc_lun_status_is_cdb_field ( void   ) 

Sends the status "FAIL because CDB field is invalid".

Definition at line 704 of file scsi_decoder.c.

References SBC_ASC_INVALID_FIELD_IN_CDB, Sbc_build_sense, Sbc_send_failed, and SBC_SENSE_KEY_ILLEGAL_REQUEST.

Referenced by sbc_inquiry(), sbc_mode_sense(), sbc_read_10(), and sbc_write_10().

void sbc_lun_status_is_fail ( void   ) 

void sbc_lun_status_is_good ( void   ) 

void sbc_lun_status_is_not_present ( void   ) 

void sbc_lun_status_is_protected ( void   ) 

Sends the status "FAILED because of write protection".

Definition at line 697 of file scsi_decoder.c.

References SBC_ASC_WRITE_PROTECTED, Sbc_build_sense, Sbc_send_failed, and SBC_SENSE_KEY_DATA_PROTECT.

Referenced by sbc_write_10().

Bool sbc_mode_sense ( Bool  b_sense_10  ) 

Manages the MODE SENSE (6) and (10) commands.

The MODE SENSE (6/10) commands provide a means for a device server to report parameters to an application client. They are complementary commands to the MODE SELECT (6/10) commands. Device servers that implement the MODE SENSE (6/10) commands shall also implement the MODE SELECT (6/10) commands.

Parameters:
b_sense_10 Boolean indicating whether the (10) version of the command is requested:
  • TRUE to specify a MODE SENSE (10) command;
  • FALSE to specify a MODE SENSE (6) command.
Returns:
Boolean indicating success.

Definition at line 358 of file scsi_decoder.c.

References g_scsi_command, sbc_header_mode_sense(), sbc_lun_status_is_cdb_field(), sbc_lun_status_is_good(), SBC_MODE_DATA_LENGTH_CODE_ALL, SBC_MODE_DATA_LENGTH_INFORMATIONAL_EXCEPTIONS, SBC_MODE_DATA_LENGTH_READ_WRITE_ERROR_RECOVERY, SBC_MSK_PAGE_CODE, SBC_PAGE_CODE_ALL, SBC_PAGE_CODE_INFORMATIONAL_EXCEPTIONS, SBC_PAGE_CODE_READ_WRITE_ERROR_RECOVERY, Sbc_valid_write_usb, send_informational_exceptions_page(), and send_read_write_error_recovery_page().

Referenced by scsi_decode_command().

00359 {
00360   U8 allocation_length = (b_sense_10) ? g_scsi_command[8] : g_scsi_command[4];
00361 
00362   // Switch for page code.
00363   switch (g_scsi_command[2] & SBC_MSK_PAGE_CODE)
00364   {
00365   case SBC_PAGE_CODE_READ_WRITE_ERROR_RECOVERY:
00366     sbc_header_mode_sense(b_sense_10, SBC_MODE_DATA_LENGTH_READ_WRITE_ERROR_RECOVERY);
00367     send_read_write_error_recovery_page(allocation_length);
00368     Sbc_valid_write_usb(SBC_MODE_DATA_LENGTH_READ_WRITE_ERROR_RECOVERY + 1);
00369     break;
00370 
00371   // Page Code: Informational Exceptions Control mode page.
00372   case SBC_PAGE_CODE_INFORMATIONAL_EXCEPTIONS:
00373     sbc_header_mode_sense(b_sense_10, SBC_MODE_DATA_LENGTH_INFORMATIONAL_EXCEPTIONS);
00374     send_informational_exceptions_page();
00375     Sbc_valid_write_usb(SBC_MODE_DATA_LENGTH_INFORMATIONAL_EXCEPTIONS + 1);
00376     break;
00377 
00378   case SBC_PAGE_CODE_ALL:
00379     if( b_sense_10 ) {
00380        sbc_header_mode_sense( b_sense_10 , (allocation_length < (SBC_MODE_DATA_LENGTH_CODE_ALL+2))? (allocation_length-2) : SBC_MODE_DATA_LENGTH_CODE_ALL );
00381     }else{
00382        sbc_header_mode_sense( b_sense_10 , (allocation_length < (SBC_MODE_DATA_LENGTH_CODE_ALL+1))? (allocation_length-1) : SBC_MODE_DATA_LENGTH_CODE_ALL );
00383     }
00384     if (allocation_length == ((b_sense_10) ? 8 : 4))
00385     {
00386       Sbc_valid_write_usb(allocation_length);
00387       break;
00388     }
00389     // Send page by ascending order code.
00390     send_read_write_error_recovery_page(allocation_length); // 12 bytes.
00391     if (allocation_length > 12)
00392     {
00393       send_informational_exceptions_page();                 // 12 bytes.
00394       Sbc_valid_write_usb(SBC_MODE_DATA_LENGTH_CODE_ALL + 1);
00395     }
00396     else
00397     {
00398       Sbc_valid_write_usb(allocation_length);
00399     }
00400     break;
00401 
00402   default:
00403     sbc_lun_status_is_cdb_field();
00404     return FALSE;
00405   }
00406 
00407   sbc_lun_status_is_good();
00408 
00409   return TRUE;
00410 }

Bool sbc_prevent_allow_medium_removal ( void   ) 

Manages the PREVENT ALLOW MEDIUM REMOVAL command.

The PREVENT ALLOW MEDIUM REMOVAL command requests that the logical unit enable or disable the removal of the medium. The logical unit shall not allow medium removal if any initiator port currently has medium removal prevented.

Returns:
Boolean indicating success.

Definition at line 413 of file scsi_decoder.c.

References sbc_lun_status_is_good().

Referenced by scsi_decode_command().

00414 {
00415   sbc_lun_status_is_good();
00416   return TRUE;
00417 }

Bool sbc_read_10 ( void   ) 

Manages the READ (10) command.

The READ (10) command requests that the device server read the specified logical block(s) and transfer them to the data-in buffer. Each logical block read includes user data and, if the medium is formatted with protection information enabled, protection information. Each logical block transferred includes user data and may include protection information, based on the RDPROTECT field and the medium format. The most recent data value written in the addressed logical block shall be returned.

Returns:
Boolean indicating success.

Definition at line 458 of file scsi_decoder.c.

References EP_MS_OUT, g_scsi_command, g_scsi_data_remaining, ms_endpoint, sbc_lun_status_is_busy_or_change(), sbc_lun_status_is_cdb_field(), sbc_lun_status_is_fail(), sbc_lun_status_is_good(), sbc_lun_status_is_not_present(), and usb_LUN.

Referenced by scsi_decode_command().

00459 {
00460   U32 mass_addr;  // Read/write block address.
00461   U16 mass_size;  // Read/write number of blocks.
00462 
00463   // Read address.
00464   MSB0W(mass_addr) = g_scsi_command[2];
00465   MSB1W(mass_addr) = g_scsi_command[3];
00466   MSB2W(mass_addr) = g_scsi_command[4];
00467   MSB3W(mass_addr) = g_scsi_command[5];
00468 
00469   // Read size.
00470   MSB(mass_size) = g_scsi_command[7];
00471   LSB(mass_size) = g_scsi_command[8];
00472 
00473   if( ms_endpoint == EP_MS_OUT )
00474   {
00475      // Error in command field
00476      sbc_lun_status_is_cdb_field();
00477      return FALSE;
00478   }
00479 
00480   // No data to transfer.
00481   if( 0 == g_scsi_data_remaining )
00482   {
00483      if( mass_size == (g_scsi_data_remaining/512) )
00484      {
00485         sbc_lun_status_is_good();
00486      }else{
00487         sbc_lun_status_is_cdb_field();
00488      }
00489      return TRUE;
00490   }
00491 
00492   switch (memory_2_usb(usb_LUN, mass_addr, g_scsi_data_remaining/512))
00493   {
00494   case CTRL_GOOD:
00495     if( mass_size == (g_scsi_data_remaining/512) )
00496     {
00497        sbc_lun_status_is_good();
00498     }else{
00499        sbc_lun_status_is_cdb_field();
00500     }
00501     g_scsi_data_remaining = 0;
00502     return TRUE;
00503 
00504   case CTRL_NO_PRESENT:
00505     sbc_lun_status_is_not_present();
00506     break;
00507 
00508   case CTRL_BUSY:
00509     sbc_lun_status_is_busy_or_change();
00510     break;
00511 
00512   case CTRL_FAIL:
00513   default:
00514     sbc_lun_status_is_fail();
00515     break;
00516   }
00517 
00518   return FALSE;
00519 }

Bool sbc_read_capacity ( void   ) 

Manages the READ CAPACITY (10) command.

The READ CAPACITY (10) command requests that the device server transfer 8 bytes of parameter data describing the capacity and medium format of the direct-access block device to the data-in buffer. This command may be processed as if it has a HEAD OF QUEUE task attribute. If the logical unit supports protection information, the application client should use the READ CAPACITY (16) command instead of the READ CAPACITY (10) command.

Returns:
Boolean indicating success.

Definition at line 420 of file scsi_decoder.c.

References g_scsi_ep_ms_in, Sbc_format_mcu_to_scsi_data, sbc_format_mcu_to_scsi_data, sbc_lun_status_is_busy_or_change(), sbc_lun_status_is_fail(), sbc_lun_status_is_good(), sbc_lun_status_is_not_present(), SBC_READ_CAPACITY_LENGTH, Sbc_valid_write_usb, and usb_LUN.

Referenced by scsi_decode_command().

00421 {
00422   U32 mem_size_nb_sector;
00423 
00424   switch (mem_read_capacity(usb_LUN, &mem_size_nb_sector))
00425   {
00426   case CTRL_GOOD:
00427     Usb_reset_endpoint_fifo_access(g_scsi_ep_ms_in);
00428 
00429     // Return nb block.
00430     Usb_write_endpoint_data(g_scsi_ep_ms_in, 32,
00431                             sbc_format_mcu_to_scsi_data(32, mem_size_nb_sector));
00432 
00433     // Return block size (= 512 bytes).
00434     Usb_write_endpoint_data(g_scsi_ep_ms_in, 32,
00435                             Sbc_format_mcu_to_scsi_data(32, 512));
00436 
00437     Sbc_valid_write_usb(SBC_READ_CAPACITY_LENGTH);
00438     sbc_lun_status_is_good();
00439     return TRUE;
00440 
00441   case CTRL_NO_PRESENT:
00442     sbc_lun_status_is_not_present();
00443     break;
00444 
00445   case CTRL_BUSY:
00446     sbc_lun_status_is_busy_or_change();
00447     break;
00448 
00449   case CTRL_FAIL:
00450   default:
00451     sbc_lun_status_is_fail();
00452     break;
00453   }
00454   return FALSE;
00455 }

Bool sbc_request_sense ( void   ) 

Manages the REQUEST SENSE command.

The REQUEST SENSE command requests that the device server transfer sense data to the application client.

See s_scsi_sense.

Returns:
Boolean indicating success.

Definition at line 281 of file scsi_decoder.c.

References s_scsi_sense::asc, s_scsi_sense::ascq, EP_MS_IN, g_scsi_command, g_scsi_ep_ms_in, s_scsi_sense::key, SBC_ADDITIONAL_SENSE_LENGTH, SBC_COMMAND_SPECIFIC_INFORMATION_0, SBC_COMMAND_SPECIFIC_INFORMATION_1, SBC_COMMAND_SPECIFIC_INFORMATION_2, SBC_COMMAND_SPECIFIC_INFORMATION_3, SBC_FIELD_REPLACEABLE_UNIT_CODE, sbc_lun_status_is_good(), SBC_RESPONSE_CODE_SENSE, SBC_SENSE_KEY_SPECIFIC_0, SBC_SENSE_KEY_SPECIFIC_1, SBC_SENSE_KEY_SPECIFIC_2, and Sbc_valid_write_usb.

Referenced by scsi_decode_command().

00282 {
00283   U8 allocation_length;
00284   U8 request_sense_output[18];  // The maximal size of request is 17.
00285 
00286   allocation_length = min(g_scsi_command[4], sizeof(request_sense_output));
00287 
00288   if( allocation_length != 0 )
00289   {
00290      // Initialize the request sense data.
00291      request_sense_output[ 0] = SBC_RESPONSE_CODE_SENSE; // 0x70.
00292      request_sense_output[ 1] = 0x00;                    // Obsolete.
00293      request_sense_output[ 2] = g_scsi_sense.key;
00294    
00295      request_sense_output[ 3] = 0x00;  // For direct access media, Information field.
00296      request_sense_output[ 4] = 0x00;  // Give the unsigned logical block.
00297      request_sense_output[ 5] = 0x00;  // Address associated with the sense key.
00298      request_sense_output[ 6] = 0x00;
00299    
00300      request_sense_output[ 7] = SBC_ADDITIONAL_SENSE_LENGTH; // Device shall not adjust the additional sense length to reflect truncation.
00301      request_sense_output[ 8] = SBC_COMMAND_SPECIFIC_INFORMATION_3;
00302      request_sense_output[ 9] = SBC_COMMAND_SPECIFIC_INFORMATION_2;
00303      request_sense_output[10] = SBC_COMMAND_SPECIFIC_INFORMATION_1;
00304      request_sense_output[11] = SBC_COMMAND_SPECIFIC_INFORMATION_0;
00305    
00306      request_sense_output[12] = g_scsi_sense.asc;
00307      request_sense_output[13] = g_scsi_sense.ascq;
00308    
00309      request_sense_output[14] = SBC_FIELD_REPLACEABLE_UNIT_CODE;
00310      request_sense_output[15] = SBC_SENSE_KEY_SPECIFIC_2;
00311      request_sense_output[16] = SBC_SENSE_KEY_SPECIFIC_1;
00312      request_sense_output[17] = SBC_SENSE_KEY_SPECIFIC_0;
00313    
00314      // Send the request data.
00315      Usb_reset_endpoint_fifo_access(g_scsi_ep_ms_in);
00316      usb_write_ep_txpacket(g_scsi_ep_ms_in, request_sense_output, allocation_length, NULL);
00317      Sbc_valid_write_usb(allocation_length);
00318      // MSC Compliance - Wait end of all transmitions on USB line, because a stall may be send after data
00319      while( 0 != Usb_nb_busy_bank(EP_MS_IN) );
00320   }
00321   sbc_lun_status_is_good();
00322   return (allocation_length == g_scsi_command[4]);
00323 }

Bool sbc_test_unit_ready ( void   ) 

Manages the TEST UNIT READY command.

The TEST UNIT READY command provides a means to check if the logical unit is ready. This is not a request for a self-test. If the logical unit is able to accept an appropriate medium-access command without returning CHECK CONDITION status, this command shall return a GOOD status. If the logical unit is unable to become operational or is in a state such that an application client action (e.g., START UNIT command) is required to make the logical unit ready, the command shall be terminated with CHECK CONDITION status, with the sense key set to NOT READY.

Returns:
Boolean indicating success.

Definition at line 255 of file scsi_decoder.c.

References sbc_lun_status_is_busy_or_change(), sbc_lun_status_is_fail(), sbc_lun_status_is_good(), sbc_lun_status_is_not_present(), and usb_LUN.

Referenced by scsi_decode_command().

00256 {
00257   switch (mem_test_unit_ready(usb_LUN))
00258   {
00259   case CTRL_GOOD:
00260     sbc_lun_status_is_good();
00261     break;
00262 
00263   case CTRL_NO_PRESENT:
00264     sbc_lun_status_is_not_present();
00265     break;
00266 
00267   case CTRL_BUSY:
00268     sbc_lun_status_is_busy_or_change();
00269     break;
00270 
00271   case CTRL_FAIL:
00272   default:
00273     sbc_lun_status_is_fail();
00274     break;
00275   }
00276 
00277   return TRUE;
00278 }

Bool sbc_write_10 ( void   ) 

Manages the WRITE (10) command.

The WRITE (10) command requests that the device server transfer the specified logical block(s) from the data-out buffer and write them. Each logical block transferred includes user data and may include protection information, based on the WRPROTECT field and the medium format. Each logical block written includes user data and, if the medium is formatted with protection information enabled, protection information.

Returns:
Boolean indicating success.

Definition at line 522 of file scsi_decoder.c.

References EP_MS_IN, g_scsi_command, g_scsi_data_remaining, ms_endpoint, sbc_lun_status_is_busy_or_change(), sbc_lun_status_is_cdb_field(), sbc_lun_status_is_fail(), sbc_lun_status_is_good(), sbc_lun_status_is_not_present(), sbc_lun_status_is_protected(), and usb_LUN.

Referenced by scsi_decode_command().

00523 {
00524   U32 mass_addr;  // Read/write block address.
00525   U16 mass_size;  // Read/write number of blocks.
00526 
00527   // Read address.
00528   MSB0W(mass_addr) = g_scsi_command[2];
00529   MSB1W(mass_addr) = g_scsi_command[3];
00530   MSB2W(mass_addr) = g_scsi_command[4];
00531   MSB3W(mass_addr) = g_scsi_command[5];
00532 
00533   // Read size.
00534   MSB(mass_size) = g_scsi_command[7];
00535   LSB(mass_size) = g_scsi_command[8];
00536 
00537   if( ms_endpoint == EP_MS_IN )
00538   {
00539      // Error in command field
00540      sbc_lun_status_is_cdb_field();
00541      return FALSE;
00542   }
00543 
00544   // No data to transfer.
00545   if( 0 == g_scsi_data_remaining )
00546   {
00547      if( mass_size == (g_scsi_data_remaining/512) )
00548      {
00549         sbc_lun_status_is_good();
00550      }else{
00551         sbc_lun_status_is_cdb_field();
00552      }
00553      return TRUE;
00554   }
00555    
00556   if (mem_wr_protect(usb_LUN))
00557   {
00558     sbc_lun_status_is_protected();
00559     return FALSE;
00560   }
00561 
00562   switch (usb_2_memory(usb_LUN, mass_addr, g_scsi_data_remaining/512 ))
00563   {
00564   case CTRL_GOOD:
00565     if( mass_size == (g_scsi_data_remaining/512) )
00566     {
00567        sbc_lun_status_is_good();
00568     }else{
00569        sbc_lun_status_is_cdb_field();
00570     }
00571     g_scsi_data_remaining = 0;
00572     return TRUE;
00573 
00574   case CTRL_NO_PRESENT:
00575     sbc_lun_status_is_not_present();
00576     break;
00577 
00578   case CTRL_BUSY:
00579     sbc_lun_status_is_busy_or_change();
00580     break;
00581 
00582   case CTRL_FAIL:
00583   default:
00584     sbc_lun_status_is_fail();
00585     break;
00586   }
00587   return FALSE;
00588 }

Bool scsi_decode_command ( void   ) 

Decodes and launches the execution of SCSI commands.

Returns:
Boolean indicating success.

Definition at line 146 of file scsi_decoder.c.

References g_scsi_command, SBC_ASC_INVALID_COMMAND_OPERATION_CODE, Sbc_build_sense, SBC_CMD_ACCESS_CONTROL_IN, SBC_CMD_ACCESS_CONTROL_OUT, SBC_CMD_EXTENDED_COPY, SBC_CMD_FORMAT_UNIT, SBC_CMD_INQUIRY, SBC_CMD_LOG_SELECT, SBC_CMD_LOG_SENSE, SBC_CMD_MODE_SELECT_10, SBC_CMD_MODE_SELECT_6, SBC_CMD_MODE_SENSE_10, SBC_CMD_MODE_SENSE_6, SBC_CMD_PERSISTENT_RESERVE_IN, SBC_CMD_PERSISTENT_RESERVE_OUT, SBC_CMD_PREFETCH_10, SBC_CMD_PREFETCH_16, SBC_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL, SBC_CMD_READ_10, SBC_CMD_READ_12, SBC_CMD_READ_16, SBC_CMD_READ_6, SBC_CMD_READ_ATTRIBUTE, SBC_CMD_READ_BUFFER, SBC_CMD_READ_CAPACITY_10, SBC_CMD_READ_DEFECT_DATA_10, SBC_CMD_READ_DEFECT_DATA_12, SBC_CMD_READ_LONG_10, SBC_CMD_REASSIGN_BLOCKS, SBC_CMD_RECEIVE_COPY_RESULTS, SBC_CMD_RECEIVE_DIAGNOSTIC_RESULTS, SBC_CMD_REPORT_LUNS, SBC_CMD_REQUEST_SENSE, SBC_CMD_SEND_DIAGNOSTIC, SBC_CMD_START_STOP_UNIT, SBC_CMD_SYNCHRONIZE_CACHE_10, SBC_CMD_SYNCHRONIZE_CACHE_16, SBC_CMD_TEST_UNIT_READY, SBC_CMD_VERIFY_10, SBC_CMD_VERIFY_12, SBC_CMD_VERIFY_16, SBC_CMD_WRITE_10, SBC_CMD_WRITE_12, SBC_CMD_WRITE_16, SBC_CMD_WRITE_6, SBC_CMD_WRITE_AND_VERIFY_10, SBC_CMD_WRITE_AND_VERIFY_12, SBC_CMD_WRITE_AND_VERIFY_16, SBC_CMD_WRITE_ATTRIBUTE, SBC_CMD_WRITE_BUFFER, SBC_CMD_WRITE_LONG_10, SBC_CMD_WRITE_SAME_10, SBC_CMD_WRITE_SAME_16, SBC_CMD_XDREAD_10, SBC_CMD_XDWRITE_10, SBC_CMD_XDWRITEREAD_10, SBC_CMD_XPWRITE_10, sbc_inquiry(), sbc_lun_status_is_good(), sbc_mode_sense(), sbc_prevent_allow_medium_removal(), sbc_read_10(), sbc_read_capacity(), sbc_request_sense(), Sbc_send_failed, SBC_SENSE_KEY_ILLEGAL_REQUEST, sbc_test_unit_ready(), sbc_write_10(), Scsi_start_read_action, Scsi_start_write_action, Scsi_stop_read_action, and Scsi_stop_write_action.

Referenced by usb_mass_storage_cbw().

00147 {
00148   Bool status = FALSE;
00149 
00150   switch (g_scsi_command[0])  // Check received command.
00151   {
00152   case SBC_CMD_TEST_UNIT_READY:               // 0x00 - Mandatory.
00153     status = sbc_test_unit_ready();
00154     break;
00155 
00156   case SBC_CMD_REQUEST_SENSE:                 // 0x03 - Mandatory.
00157     status = sbc_request_sense();
00158     break;
00159 
00160   case SBC_CMD_INQUIRY:                       // 0x12 - Mandatory.
00161     status = sbc_inquiry();
00162     break;
00163 
00164   case SBC_CMD_MODE_SENSE_6:                  // 0x1A - Optional.
00165     status = sbc_mode_sense(FALSE);
00166     break;
00167 
00168   case SBC_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:  // 0x1E - Optional.
00169     status = sbc_prevent_allow_medium_removal();
00170     break;
00171 
00172   case SBC_CMD_READ_CAPACITY_10:              // 0x25 - Mandatory.
00173     status = sbc_read_capacity();
00174     break;
00175 
00176   case SBC_CMD_READ_10:                       // 0x28 - Mandatory.
00177     Scsi_start_read_action();
00178     status = sbc_read_10();
00179     Scsi_stop_read_action();
00180     break;
00181 
00182   case SBC_CMD_WRITE_10:                      // 0x2A - Optional.
00183     Scsi_start_write_action();
00184     status = sbc_write_10();
00185     Scsi_stop_write_action();
00186     break;
00187 
00188   case SBC_CMD_VERIFY_10:                     // 0x2F - Optional.
00189     status = TRUE;
00190     sbc_lun_status_is_good();
00191     break;
00192 
00193   case SBC_CMD_MODE_SENSE_10:                 // 0x5A - Optional.
00194     status = sbc_mode_sense(TRUE);
00195     break;
00196 
00197   case SBC_CMD_START_STOP_UNIT:               // 0x1B - Ignored. This command is used by the Linux 2.4 kernel,
00198     break;                                    // for which we can not reply INVALID COMMAND, otherwise the disk will not mount.
00199 
00200   case SBC_CMD_FORMAT_UNIT:                   // 0x04 - Mandatory.
00201   case SBC_CMD_REASSIGN_BLOCKS:               // 0x07 - Optional.
00202   case SBC_CMD_READ_6:                        // 0x08 - Mandatory.
00203   case SBC_CMD_WRITE_6:                       // 0x0A - Optional.
00204   case SBC_CMD_MODE_SELECT_6:                 // 0x15 - Optional.
00205   case SBC_CMD_RECEIVE_DIAGNOSTIC_RESULTS:    // 0x1C - Optional.
00206   case SBC_CMD_SEND_DIAGNOSTIC:               // 0x1D - Mandatory.
00207   case SBC_CMD_WRITE_AND_VERIFY_10:           // 0x2E - Optional.
00208   case SBC_CMD_PREFETCH_10:                   // 0x34 - Optional.
00209   case SBC_CMD_SYNCHRONIZE_CACHE_10:          // 0x35 - Optional.
00210   case SBC_CMD_READ_DEFECT_DATA_10:           // 0x37 - Optional.
00211   case SBC_CMD_WRITE_BUFFER:                  // 0x3B - Optional.
00212   case SBC_CMD_READ_BUFFER:                   // 0x3C - Optional.
00213   case SBC_CMD_READ_LONG_10:                  // 0x3E - Optional.
00214   case SBC_CMD_WRITE_LONG_10:                 // 0x3F - Optional.
00215   case SBC_CMD_WRITE_SAME_10:                 // 0x41 - Optional.
00216   case SBC_CMD_LOG_SELECT:                    // 0x4C - Optional.
00217   case SBC_CMD_LOG_SENSE:                     // 0x4D - Optional.
00218   case SBC_CMD_XDWRITE_10:                    // 0x50 - Optional.
00219   case SBC_CMD_XPWRITE_10:                    // 0x51 - Optional.
00220   case SBC_CMD_XDREAD_10:                     // 0x52 - Optional.
00221   case SBC_CMD_XDWRITEREAD_10:                // 0x53 - Optional.
00222   case SBC_CMD_MODE_SELECT_10:                // 0x55 - Optional.
00223   case SBC_CMD_PERSISTENT_RESERVE_IN:         // 0x5E - Optional.
00224   case SBC_CMD_PERSISTENT_RESERVE_OUT:        // 0x5F - Optional.
00225   case SBC_CMD_EXTENDED_COPY:                 // 0x83 - Optional.
00226   case SBC_CMD_RECEIVE_COPY_RESULTS:          // 0x84 - Optional.
00227   case SBC_CMD_ACCESS_CONTROL_IN:             // 0x86 - Optional.
00228   case SBC_CMD_ACCESS_CONTROL_OUT:            // 0x87 - Optional.
00229   case SBC_CMD_READ_16:                       // 0x88 - Optional.
00230   case SBC_CMD_WRITE_16:                      // 0x8A - Optional.
00231   case SBC_CMD_READ_ATTRIBUTE:                // 0x8C - Optional.
00232   case SBC_CMD_WRITE_ATTRIBUTE:               // 0x8D - Optional.
00233   case SBC_CMD_WRITE_AND_VERIFY_16:           // 0x8E - Optional.
00234   case SBC_CMD_VERIFY_16:                     // 0x8F - Optional.
00235   case SBC_CMD_PREFETCH_16:                   // 0x90 - Optional.
00236   case SBC_CMD_SYNCHRONIZE_CACHE_16:          // 0x91 - Optional.
00237   case SBC_CMD_WRITE_SAME_16:                 // 0x93 - Optional.
00238   case SBC_CMD_REPORT_LUNS:                   // 0xA0 - Mandator.
00239   case SBC_CMD_READ_12:                       // 0xA8 - Optional.
00240   case SBC_CMD_WRITE_12:                      // 0xAA - Optional.
00241   case SBC_CMD_WRITE_AND_VERIFY_12:           // 0xAE - Optional.
00242   case SBC_CMD_VERIFY_12:                     // 0xAF - Optional.
00243   case SBC_CMD_READ_DEFECT_DATA_12:           // 0xB7 - Optional.
00244   default:
00245     // Command not supported.
00246     Sbc_send_failed();
00247     Sbc_build_sense(SBC_SENSE_KEY_ILLEGAL_REQUEST, SBC_ASC_INVALID_COMMAND_OPERATION_CODE, 0x00);
00248     break;
00249   }
00250 
00251   return status;
00252 }

static void send_informational_exceptions_page ( void   )  [static]

Writes the Informational Exceptions Control mode page.

Definition at line 649 of file scsi_decoder.c.

References g_scsi_ep_ms_in, Sbc_format_mcu_to_scsi_data, SBC_MRIE_GENERATE_NO_SENSE, SBC_PAGE_CODE_INFORMATIONAL_EXCEPTIONS, and SBC_PAGE_LENGTH_INFORMATIONAL_EXCEPTIONS.

Referenced by sbc_mode_sense().

00650 {
00651   // Page Code: Informational Exceptions Control mode page.
00652   Usb_write_endpoint_data(g_scsi_ep_ms_in, 8, SBC_PAGE_CODE_INFORMATIONAL_EXCEPTIONS);
00653 
00654   // Page Length.
00655   Usb_write_endpoint_data(g_scsi_ep_ms_in, 8, SBC_PAGE_LENGTH_INFORMATIONAL_EXCEPTIONS);
00656   // ..., test bit = 0, ...
00657   Usb_write_endpoint_data(g_scsi_ep_ms_in, 8, 0x00);
00658   // MRIE = 0x05.
00659   Usb_write_endpoint_data(g_scsi_ep_ms_in, 8, SBC_MRIE_GENERATE_NO_SENSE);
00660   // Interval Timer.
00661   Usb_write_endpoint_data(g_scsi_ep_ms_in, 32,
00662                           Sbc_format_mcu_to_scsi_data(32, 0x00000000));
00663   // Report Count.
00664   Usb_write_endpoint_data(g_scsi_ep_ms_in, 32,
00665                           Sbc_format_mcu_to_scsi_data(32, 0x00000001));
00666 }

static void send_read_write_error_recovery_page ( U8  length  )  [static]

Writes the Error Recovery mode page.

Parameters:
length Allocated data length in bytes.

Definition at line 625 of file scsi_decoder.c.

References g_scsi_ep_ms_in, Sbc_format_mcu_to_scsi_data, SBC_PAGE_CODE_READ_WRITE_ERROR_RECOVERY, SBC_PAGE_LENGTH_READ_WRITE_ERROR_RECOVERY, SBC_READ_RETRY_COUNT, SBC_RECOVERY_TIME_LIMIT, and SBC_WRITE_RETRY_COUNT.

Referenced by sbc_mode_sense().

00626 {
00627   Usb_write_endpoint_data(g_scsi_ep_ms_in, 8, SBC_PAGE_CODE_READ_WRITE_ERROR_RECOVERY);
00628 
00629   // Page Length.
00630   Usb_write_endpoint_data(g_scsi_ep_ms_in, 8, SBC_PAGE_LENGTH_READ_WRITE_ERROR_RECOVERY);
00631   Usb_write_endpoint_data(g_scsi_ep_ms_in, 8, 0x80);
00632   Usb_write_endpoint_data(g_scsi_ep_ms_in, 8, SBC_READ_RETRY_COUNT);
00633   Usb_write_endpoint_data(g_scsi_ep_ms_in, 8, 0x00);
00634   Usb_write_endpoint_data(g_scsi_ep_ms_in, 8, 0x00);
00635   Usb_write_endpoint_data(g_scsi_ep_ms_in, 8, 0x00);
00636   // Reserved.
00637   Usb_write_endpoint_data(g_scsi_ep_ms_in, 8, 0x00);
00638 
00639   if (length > 12)
00640   {
00641     Usb_write_endpoint_data(g_scsi_ep_ms_in, 8, SBC_WRITE_RETRY_COUNT);
00642     Usb_write_endpoint_data(g_scsi_ep_ms_in, 8, 0x00);
00643     Usb_write_endpoint_data(g_scsi_ep_ms_in, 16,
00644                             Sbc_format_mcu_to_scsi_data(16, SBC_RECOVERY_TIME_LIMIT));
00645   }
00646 }


Variable Documentation

Remaining data transfer length.

Definition at line 91 of file scsi_decoder.c.

Referenced by sbc_read_10(), sbc_write_10(), usb_mass_storage_cbw(), and usb_mass_storage_csw().

USB mass-storage OUT endpoint.

Definition at line 96 of file scsi_decoder.c.

Referenced by device_mass_storage_task_init(), and virtual_usb_write_10().

Sense data.

Definition at line 93 of file scsi_decoder.c.

SCSI status.

Definition at line 90 of file scsi_decoder.c.

Referenced by usb_mass_storage_csw().

Definition at line 82 of file device_mass_storage_task.c.

Referenced by sbc_read_10(), sbc_write_10(), and usb_mass_storage_cbw().

INQUIRY data.

Definition at line 99 of file scsi_decoder.c.

U8 usb_LUN


Generated on Fri Feb 19 02:33:38 2010 for AVR32 - USB Mass-Storage on FreeRTOS Example by  doxygen 1.5.5