scsi_decoder.c

Go to the documentation of this file.
00001 /*This file is prepared for Doxygen automatic documentation generation.*/
00015 
00016 /* Copyright (c) 2009 Atmel Corporation. All rights reserved.
00017  *
00018  * Redistribution and use in source and binary forms, with or without
00019  * modification, are permitted provided that the following conditions are met:
00020  *
00021  * 1. Redistributions of source code must retain the above copyright notice,
00022  * this list of conditions and the following disclaimer.
00023  *
00024  * 2. Redistributions in binary form must reproduce the above copyright notice,
00025  * this list of conditions and the following disclaimer in the documentation
00026  * and/or other materials provided with the distribution.
00027  *
00028  * 3. The name of Atmel may not be used to endorse or promote products derived
00029  * from this software without specific prior written permission.
00030  *
00031  * 4. This software may only be redistributed and used in connection with an Atmel
00032  * AVR product.
00033  *
00034  * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
00035  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00036  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE EXPRESSLY AND
00037  * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
00038  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00039  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00040  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00041  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00042  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00043  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00044  */
00045 
00046 //_____  I N C L U D E S ___________________________________________________
00047 
00048 #include "config.h"
00049 #include "scsi_decoder.h"
00050 #include "storage_task.h"
00051 #include "conf_usb.h"
00052 #include "lib_mcu/usb/usb_drv.h"
00053 #include "modules/control_access/ctrl_status.h"
00054 #include "modules/control_access/ctrl_access.h"
00055 
00056 
00057 //_____ D E F I N I T I O N S ______________________________________________
00058 
00059 U8  g_scsi_command[16];
00060 U8  g_scsi_status;
00061 U32 g_scsi_data_remaining;
00062 
00063 code    U8    g_sbc_vendor_id[8]   = SBC_VENDOR_ID;
00064 code    U8    g_sbc_product_id[16] = SBC_PRODUCT_ID;
00065 code    U8    g_sbc_revision_id[4] = SBC_REVISION_ID;
00066 
00067 extern  U8    usb_LUN;
00068 extern  bit   ms_data_direction;
00069 s_scsi_sense  g_scsi_sense;
00070 
00071 
00072 code  struct sbc_st_std_inquiry_data sbc_std_inquiry_data =
00073 {
00074    // Byte 0 : 0x00
00075    0x00,       // DeviceType: Direct-access device (SBC)
00076    0,          // PeripheralQualifier : Currently connected
00077 
00078    // Byte 1 : 0x80
00079    0,          // Reserved1
00080    1,          // RMB : Medium is removable (this bit must be at 1, else the medium isn't see on Windows)
00081 
00082    // Byte 2 : The code in the VERSION corresponds to a command set of DeviceType (here, Direct-access device - SBC)
00083    0x03,       // - 00h The device does not claim conformance to any standard.
00084                // - 03h The device complies to SPC (=SBC)
00085                // - 04h The device complies to SPC-2 (=SBC-2)
00086                // - 05h The device complies to SPC-3 (=SBC-2)
00087                // - 06h The device complies to SPC-4 (=SBC-3)
00088 
00089    // Byte 3 : 0x02
00090    2,          // Response data format
00091    0,          // NormACA
00092    0,          // Obsolete0
00093    0,          // AERC
00094 
00095    // Byte 4 : 0x1F
00096    // Byte 5 : 0x00
00097    // Byte 6 : 0x00
00098                // Reserved4[3]
00099    {
00100       0x1F,    // Additional Length (n-4)
00101       0,       // SCCS : SCC supported
00102       0
00103    },
00104 
00105    // Byte 7 : 0x00
00106    0,          // SoftReset
00107    0,          // CommandQueue
00108    0,          // Reserved5
00109    0,          // LinkedCommands
00110    0,          // Synchronous
00111    0,          // Wide16Bit
00112    0,          // Wide32Bit
00113    0,          // RelativeAddressing
00114 };
00115 
00116 
00117 static   void  send_informational_exceptions_page  (void);
00118 static   void  send_read_write_error_recovery_page (U8);
00119 static   void  sbc_header_mode_sense               ( Bool b_sense_10 , U8 u8_data_length );
00120 
00121 
00122 //_____ D E C L A R A T I O N S ____________________________________________
00123 
00124 
00138 Bool scsi_decode_command(void)
00139 {
00140    Bool status;
00141 
00142    if (g_scsi_command[0] == SBC_CMD_WRITE_10)
00143    {
00144       Scsi_start_write_action();
00145       status = sbc_write_10();
00146       Scsi_stop_write_action();
00147       return status;
00148    }
00149    if (g_scsi_command[0] == SBC_CMD_READ_10 )
00150    {
00151       Scsi_start_read_action();
00152       status = sbc_read_10();
00153       Scsi_stop_read_action();
00154       return status;
00155    }
00156 
00157    switch (g_scsi_command[0])
00158    {
00159       case SBC_CMD_REQUEST_SENSE:               // 0x03 - Mandatory
00160       return sbc_request_sense();
00161       break;
00162 
00163       case SBC_CMD_INQUIRY:                     // 0x12 - Mandatory
00164       return sbc_inquiry();
00165       break;
00166 
00167       case SBC_CMD_TEST_UNIT_READY:             // 0x00 - Mandatory
00168       return sbc_test_unit_ready();
00169       break;
00170 
00171       case SBC_CMD_READ_CAPACITY:               // 0x25 - Mandatory
00172       return sbc_read_capacity();
00173       break;
00174 
00175       case SBC_CMD_MODE_SENSE_6:                // 0x1A - Optional
00176       return sbc_mode_sense( FALSE );
00177       break;
00178 
00179       case SBC_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:// 0x1E
00180       return sbc_prevent_allow_medium_removal();
00181       break;
00182 
00183       case SBC_CMD_VERIFY_10:                   // 0x2F - Optional
00184       sbc_lun_status_is_good();
00185       break;
00186 
00187       case SBC_CMD_MODE_SENSE_10:               // 0x5A - Optional
00188       return sbc_mode_sense( TRUE );
00189       break;
00190 
00191       case SBC_CMD_START_STOP_UNIT:             // 0x1B - Optional but ignored because this command is used by the Linux 2.4 kernel,
00192       sbc_lun_status_is_good();                 // for which we can not reply INVALID COMMAND, otherwise the disk will not mount.
00193       break;                                    
00194 
00195       case SBC_CMD_FORMAT_UNIT:                 // 0x04 - Mandatory
00196       case SBC_CMD_MODE_SELECT_6:               // 0x15 - Optional
00197       case SBC_CMD_SEND_DIAGNOSTIC:             // 0x1D - 
00198       case SBC_CMD_READ_LONG:                   // 0x23 - Optional
00199       case SBC_CMD_SYNCHRONIZE_CACHE:           // 0x35 - Optional
00200       case SBC_CMD_WRITE_BUFFER:                // 0x3B - Optional
00201       case SBC_CMD_RESERVE_10:                  // 0x56 - Mandatory
00202       case SBC_CMD_RELEASE_10:                  // 0x57 - Mandatory - see chapter 7.16 - SPC 2
00203       default:
00204       // Command not supported
00205       Sbc_send_failed();
00206       Sbc_build_sense(SBC_SENSE_KEY_ILLEGAL_REQUEST, SBC_ASC_INVALID_COMMAND_OPERATION_CODE, 0x00);
00207       return FALSE;
00208       break;
00209    }
00210    return TRUE;
00211 }
00212 
00213 
00231 Bool sbc_request_sense (void)
00232 {
00233    U8  allocation_length, i;
00234    U8  request_sens_output[18];                             // the maximum size of request is 17
00235 
00236    allocation_length = g_scsi_command[4];                   // Allocation length
00237    if( allocation_length > 18 )
00238    {
00239       allocation_length = 18;
00240    }
00241    // Initialize the request sense data
00242    request_sens_output[0] = SBC_RESPONSE_CODE_SENSE;        // 70h
00243    request_sens_output[1] = 0x00;                           // Obsolete
00244    request_sens_output[2] = g_scsi_sense.key;
00245 
00246    request_sens_output[3] = 0x00;                           // For direct access media, Information field
00247    request_sens_output[4] = 0x00;                           // give the unsigned logical block
00248    request_sens_output[5] = 0x00;                           // address associated with the sense key
00249    request_sens_output[6] = 0x00;
00250 
00251    request_sens_output[7] = SBC_ADDITIONAL_SENSE_LENGTH;    // UFI device shall not adjust the Additional sense length to reflect truncation
00252    request_sens_output[8] = SBC_COMMAND_SPECIFIC_INFORMATION_3;
00253    request_sens_output[9] = SBC_COMMAND_SPECIFIC_INFORMATION_2;
00254    request_sens_output[10] = SBC_COMMAND_SPECIFIC_INFORMATION_1;
00255    request_sens_output[11] = SBC_COMMAND_SPECIFIC_INFORMATION_0;
00256 
00257    request_sens_output[12] = g_scsi_sense.asc;
00258    request_sens_output[13] = g_scsi_sense.ascq;
00259 
00260    request_sens_output[14] = SBC_FIELD_REPLACEABLE_UNIT_CODE;
00261    request_sens_output[15] = SBC_SENSE_KEY_SPECIFIC_2;
00262    request_sens_output[16] = SBC_SENSE_KEY_SPECIFIC_1;
00263    request_sens_output[17] = SBC_SENSE_KEY_SPECIFIC_0;
00264 
00265    // Send the request data
00266    for( i=0 ; i<allocation_length ; i++ )
00267    {
00268        Usb_write_byte( request_sens_output[i] );
00269    }
00270    Sbc_valid_write_usb( allocation_length );
00271 
00272    sbc_lun_status_is_good();
00273    return TRUE;
00274 }
00275 
00276 
00296 Bool sbc_inquiry (void)
00297 {
00298    U8 allocation_length, i;
00299 
00300 #ifdef __GNUC__
00301    PGM_VOID_P ptr;
00302 #else
00303    U8 code *ptr;
00304 #endif
00305 
00306    if( (0 != (g_scsi_command[1] & 0x03) )       // CMDT and EPVD bits are 0
00307    ||  (0 !=  g_scsi_command[2]         ) )     // PAGE or OPERATION CODE fields = 0x00?
00308    {  
00309       // (CMDT=EVPD <> 0) or (PAGE CODE <> 0x00)
00310       // No standard inquiry asked
00311       sbc_lun_status_is_cdb_field();
00312       return FALSE;
00313    }
00314 
00315    // Manage the standard inquiry command
00316    // Check the size of inquiry data
00317    allocation_length = g_scsi_command[4];
00318    if (allocation_length > SBC_MAX_INQUIRY_DATA)
00319    {
00320       allocation_length = SBC_MAX_INQUIRY_DATA;
00321    }
00322 
00323    // send first inquiry data (0 to 8)
00324    ptr = (code U8*) &sbc_std_inquiry_data;
00325 
00326    for ( i=0 ; ((i != 36) && (allocation_length > i)); i++)
00327    {
00328       if( 8 == i )
00329       {  // send vendor id (8 to 16)
00330            ptr = (code U8 *) &g_sbc_vendor_id;
00331       }
00332       if( 16 == i )
00333       {  // send product id (16 to 32)
00334          ptr = (code U8 *) &g_sbc_product_id;
00335       }
00336       if( 32 == i )
00337       {  // send revision id (32 to 36)
00338          ptr = (code U8 *) &g_sbc_revision_id;
00339       }
00340 #ifndef __GNUC__
00341       Usb_write_byte((U8)(*ptr++));
00342 #else    // AVRGCC does not support point to PGM space
00343 //warning with AVRGCC assumes devices descriptors are stored in the lower 64Kbytes of on-chip flash memory
00344       Usb_write_byte(pgm_read_byte_near((unsigned int)ptr++));
00345 #endif
00346 
00347    }
00348    Sbc_valid_write_usb(i);
00349    sbc_lun_status_is_good();
00350    return TRUE;      
00351 }
00352 
00353 
00354 Bool sbc_test_unit_ready(void)
00355 {
00356    switch ( mem_test_unit_ready(usb_LUN) )
00357    {
00358       case CTRL_GOOD :
00359       sbc_lun_status_is_good();
00360       break;
00361 
00362       case CTRL_NO_PRESENT :
00363       sbc_lun_status_is_not_present();
00364       break;
00365 
00366       case CTRL_BUSY :
00367       sbc_lun_status_is_busy_or_change();
00368       break;
00369 
00370       case CTRL_FAIL :
00371       default :
00372       sbc_lun_status_is_fail();
00373       break;
00374    }
00375    return TRUE;
00376 }
00377 
00378 
00379 Bool sbc_read_capacity (void)
00380 {
00381    U32 mem_size_nb_sector;
00382 
00383    switch ( mem_read_capacity( usb_LUN, &mem_size_nb_sector ) )
00384    {
00385       case CTRL_GOOD :
00386       Usb_write_byte(MSB0(mem_size_nb_sector));    // return nb block
00387       Usb_write_byte(MSB1(mem_size_nb_sector));
00388       Usb_write_byte(MSB2(mem_size_nb_sector));
00389       Usb_write_byte(MSB3(mem_size_nb_sector));
00390       Usb_write_byte( 0               );           // return block size (= 512B)
00391       Usb_write_byte( 0               );
00392       Usb_write_byte( (U8)(512 >> 8)  );
00393       Usb_write_byte( (U8)(512 & 0xFF));
00394 
00395       Sbc_valid_write_usb(SBC_READ_CAPACITY_LENGTH);
00396       sbc_lun_status_is_good();
00397       return TRUE;
00398       break;
00399 
00400       case CTRL_NO_PRESENT :
00401       sbc_lun_status_is_not_present();
00402       break;
00403 
00404       case CTRL_BUSY :
00405       sbc_lun_status_is_busy_or_change();
00406       break;
00407 
00408       case CTRL_FAIL :
00409       default :
00410       sbc_lun_status_is_fail();
00411       break;
00412    }
00413    return FALSE;
00414 }
00415 
00416 
00417 Bool sbc_read_10 (void)
00418 {
00419    U32   mass_addr;                       // rd or wr block address
00420    U16   mass_size;                       // rd or write nb of blocks
00421 
00422    MSB0(mass_addr) = g_scsi_command[2];   // read address
00423    MSB1(mass_addr) = g_scsi_command[3];
00424    MSB2(mass_addr) = g_scsi_command[4];
00425    MSB3(mass_addr) = g_scsi_command[5];
00426 
00427    MSB(mass_size) = g_scsi_command[7];    // read size
00428    LSB(mass_size) = g_scsi_command[8];
00429    
00430    if( Is_usb_ms_data_direction_out() )
00431    {
00432       sbc_lun_status_is_cdb_field();
00433       return FALSE;
00434    }
00435    if( 0 == g_scsi_data_remaining )
00436    {
00437       if( mass_size == (g_scsi_data_remaining/512) )
00438       {
00439          sbc_lun_status_is_good();
00440       }else{
00441          sbc_lun_status_is_cdb_field();
00442       }
00443       return TRUE;
00444    }
00445 
00446    switch ( memory_2_usb( usb_LUN , mass_addr,  g_scsi_data_remaining/512 ) )
00447    {
00448       case CTRL_GOOD :
00449       if( mass_size == (g_scsi_data_remaining/512) )
00450       {
00451          sbc_lun_status_is_good();
00452       }else{
00453          sbc_lun_status_is_cdb_field();
00454       }
00455       g_scsi_data_remaining = 0;
00456       break;
00457 
00458       case CTRL_NO_PRESENT :
00459       sbc_lun_status_is_not_present();
00460       return FALSE;
00461       break;
00462 
00463       case CTRL_BUSY :
00464       sbc_lun_status_is_busy_or_change();
00465       return FALSE;
00466       break;
00467 
00468       case CTRL_FAIL :
00469       default :
00470       sbc_lun_status_is_fail();
00471       return FALSE;
00472       break;
00473    }
00474    return TRUE;
00475 }
00476 
00477 
00478 Bool sbc_write_10 (void)
00479 {
00480    U32   mass_addr;                       // rd or wr block address
00481    U16   mass_size;                       // rd or write nb of blocks
00482 
00483    MSB0(mass_addr) = g_scsi_command[2];   // read address
00484    MSB1(mass_addr) = g_scsi_command[3];
00485    MSB2(mass_addr) = g_scsi_command[4];
00486    MSB3(mass_addr) = g_scsi_command[5];
00487 
00488    MSB(mass_size) = g_scsi_command[7];    // read size
00489    LSB(mass_size) = g_scsi_command[8];
00490    
00491    if( Is_usb_ms_data_direction_in() )
00492    {
00493       sbc_lun_status_is_cdb_field();
00494       return FALSE;
00495    }
00496 
00497    if( 0 == g_scsi_data_remaining )
00498    {
00499       if( mass_size == (g_scsi_data_remaining/512) )
00500       {
00501          sbc_lun_status_is_good();
00502       }else{
00503          sbc_lun_status_is_cdb_field();
00504       }
00505       return TRUE;
00506    }
00507    
00508    if( TRUE == mem_wr_protect( usb_LUN ) )
00509    {
00510       sbc_lun_status_is_protected();
00511       return FALSE;
00512    }
00513 
00514    switch (usb_2_memory( usb_LUN , mass_addr, g_scsi_data_remaining/512 ))
00515    {
00516       case CTRL_GOOD :
00517       if( mass_size == (g_scsi_data_remaining/512) )
00518       {
00519          sbc_lun_status_is_good();
00520       }else{
00521          sbc_lun_status_is_cdb_field();
00522       }
00523       g_scsi_data_remaining = 0;
00524       break;
00525 
00526       case CTRL_NO_PRESENT :
00527       sbc_lun_status_is_not_present();
00528       return FALSE;
00529       break;
00530 
00531       case CTRL_BUSY :
00532       sbc_lun_status_is_busy_or_change();
00533       return FALSE;
00534       break;
00535 
00536       case CTRL_FAIL :
00537       default :
00538       sbc_lun_status_is_fail();
00539       return FALSE;
00540       break;
00541    }
00542    return TRUE;
00543 }
00544 
00545 
00560 Bool sbc_mode_sense( Bool b_sense_10 )
00561 {
00562    U8 allocation_length;
00563 
00564    if( b_sense_10 )
00565       allocation_length = g_scsi_command[8];
00566    else
00567       allocation_length = g_scsi_command[4];
00568 
00569    // switch for page code
00570    switch ( g_scsi_command[2] & SBC_MSK_PAGE_CODE )
00571    {
00572       case SBC_PAGE_CODE_INFORMATIONAL_EXCEPTIONS:
00573       sbc_header_mode_sense( b_sense_10 , SBC_MODE_DATA_LENGTH_INFORMATIONAL_EXCEPTIONS );
00574       send_informational_exceptions_page();
00575       Sbc_valid_write_usb(SBC_MODE_DATA_LENGTH_INFORMATIONAL_EXCEPTIONS + 1);
00576       break;
00577 
00578       case SBC_PAGE_CODE_READ_WRITE_ERROR_RECOVERY:
00579       sbc_header_mode_sense( b_sense_10 , SBC_MODE_DATA_LENGTH_READ_WRITE_ERROR_RECOVERY );
00580       send_read_write_error_recovery_page(allocation_length);
00581       Sbc_valid_write_usb(SBC_MODE_DATA_LENGTH_READ_WRITE_ERROR_RECOVERY + 1);
00582       break;
00583 
00584       case SBC_PAGE_CODE_ALL:
00585       if( b_sense_10 ) {
00586          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 );
00587       }else{
00588          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 );
00589       }
00590       if( b_sense_10 )
00591       {
00592          if (allocation_length == 8)
00593          {
00594             Sbc_valid_write_usb(8);
00595             break;
00596          }
00597       }
00598       else
00599       {
00600          if (allocation_length == 4)
00601          {
00602             Sbc_valid_write_usb(4);
00603             break;
00604          }
00605       }
00606       // send page by ascending order code
00607       send_read_write_error_recovery_page(allocation_length);  // 12 bytes
00608       if (allocation_length > 12)
00609       {
00610          send_informational_exceptions_page();                 // 12 bytes
00611          Sbc_valid_write_usb(SBC_MODE_DATA_LENGTH_CODE_ALL + 1);
00612       }
00613       else
00614       {
00615          Sbc_valid_write_usb(allocation_length);
00616       }
00617       break;
00618 
00619       default:
00620       sbc_lun_status_is_cdb_field();
00621       return FALSE;
00622       break;
00623    }
00624    sbc_lun_status_is_good();
00625    return TRUE;
00626 }
00627 
00628 
00636 void sbc_header_mode_sense( Bool b_sense_10 , U8 u8_data_length )
00637 {
00638    // Send Data length
00639    if( b_sense_10 )
00640    {
00641       Usb_write_byte(0);
00642    }
00643    Usb_write_byte( u8_data_length );
00644 
00645    // Send device type
00646    Usb_write_byte(SBC_MEDIUM_TYPE);
00647 
00648    // Write protect status
00649    if (mem_wr_protect( usb_LUN ))
00650    {
00651       Usb_write_byte(SBC_DEV_SPEC_PARAM_WR_PROTECT);  // Device is write protected
00652    }
00653    else
00654    {
00655       Usb_write_byte(SBC_DEV_SPEC_PARAM_WR_ENABLE);   // Device is write enabled
00656    }
00657 
00658    if( b_sense_10 )
00659    {  // Reserved
00660       Usb_write_byte(0);
00661       Usb_write_byte(0);
00662    }
00663 
00664    // Send Block descriptor length
00665    if( b_sense_10 )
00666    {
00667       Usb_write_byte(0);
00668    }
00669    Usb_write_byte(SBC_BLOCK_DESCRIPTOR_LENGTH);
00670 }
00671 
00672 
00684 void send_informational_exceptions_page (void)
00685 {
00686    Usb_write_byte(SBC_PAGE_CODE_INFORMATIONAL_EXCEPTIONS);     // Page Code: Informational exceptions control page
00687                                                                // See chapter 8.3.8 on SPC-2 specification
00688    Usb_write_byte(SBC_PAGE_LENGTH_INFORMATIONAL_EXCEPTIONS);   // Page Length
00689    Usb_write_byte(0x00);                                       // ..., Test bit = 0, ...
00690    Usb_write_byte(SBC_MRIE);                                   // MRIE = 0x05
00691    Usb_write_byte(0x00);                                       // Interval Timer (MSB)
00692    Usb_write_byte(0x00);
00693    Usb_write_byte(0x00);
00694    Usb_write_byte(0x00);                                       // Interval Timer (LSB)
00695    Usb_write_byte(0x00);                                       // Report Count (MSB)
00696    Usb_write_byte(0x00);
00697    Usb_write_byte(0x00);
00698    Usb_write_byte(0x01);                                       // Report Count (LSB)
00699 }
00700 
00701 
00713 void send_read_write_error_recovery_page (U8 length)
00714 {
00715    Usb_write_byte(SBC_PAGE_CODE_READ_WRITE_ERROR_RECOVERY);
00716 
00717    Usb_write_byte(SBC_PAGE_LENGTH_READ_WRITE_ERROR_RECOVERY);   // Page Length
00718    Usb_write_byte(0x80);
00719    Usb_write_byte(SBC_READ_RETRY_COUNT);
00720    Usb_write_byte(SBC_CORRECTION_SPAN);
00721    Usb_write_byte(SBC_HEAD_OFFSET_COUNT);
00722    Usb_write_byte(SBC_DATA_STROBE_OFFSET);
00723    Usb_write_byte(0x00);   // Reserved
00724 
00725    if (length > 12)
00726    {
00727       Usb_write_byte(SBC_WRITE_RETRY_COUNT);
00728       Usb_write_byte(0x00);
00729       Usb_write_byte(SBC_RECOVERY_LIMIT_MSB);
00730       Usb_write_byte(SBC_RECOVERY_LIMIT_LSB);
00731    }
00732 }
00733 
00749 Bool sbc_prevent_allow_medium_removal(void)
00750 {
00751    sbc_lun_status_is_good();
00752    return TRUE;
00753 }
00754 
00755 
00758 void sbc_lun_status_is_good(void)
00759 {
00760    Sbc_send_good();
00761    Sbc_build_sense(SBC_SENSE_KEY_NO_SENSE, SBC_ASC_NO_ADDITIONAL_SENSE_INFORMATION, 0x00);
00762 }
00763 
00766 void sbc_lun_status_is_not_present(void)
00767 {
00768    Sbc_send_failed();
00769    Sbc_build_sense(SBC_SENSE_KEY_NOT_READY, SBC_ASC_MEDIUM_NOT_PRESENT, 0x00);
00770 }
00771 
00774 void sbc_lun_status_is_busy_or_change(void)
00775 {
00776    Sbc_send_failed();
00777    Sbc_build_sense(SBC_SENSE_KEY_UNIT_ATTENTION, SBC_ASC_NOT_READY_TO_READY_CHANGE, 0x00 );
00778 }
00779 
00782 void sbc_lun_status_is_fail(void)
00783 {
00784    Sbc_send_failed();
00785    Sbc_build_sense(SBC_SENSE_KEY_HARDWARE_ERROR, SBC_ASC_NO_ADDITIONAL_SENSE_INFORMATION, 0x00);
00786 }
00787 
00790 void sbc_lun_status_is_protected(void)
00791 {
00792    Sbc_send_failed();
00793    Sbc_build_sense(SBC_SENSE_KEY_DATA_PROTECT, SBC_ASC_WRITE_PROTECTED, 0x00);
00794 }
00795 
00798 void sbc_lun_status_is_cdb_field(void)
00799 {
00800    Sbc_send_failed();
00801    Sbc_build_sense(SBC_SENSE_KEY_ILLEGAL_REQUEST, SBC_ASC_INVALID_FIELD_IN_CDB, 0x00);
00802 }
00803 

Generated on Wed Sep 23 09:17:02 2009 for ATMEL by  doxygen 1.5.3