ATMEL: scsi_decoder.c Source File

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

# 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