- Main Page
- Modules
- Data Structures
- Files
- Related Pages

# scsi_decoder.c

Go to the documentation of this file.

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