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       Usb_write_byte(pgm_read_byte_near((unsigned int)ptr++));
00344 #endif
00345 
00346    }
00347    Sbc_valid_write_usb(i);
00348    sbc_lun_status_is_good();
00349    return TRUE;      
00350 }
00351 
00352 
00353 Bool sbc_test_unit_ready(void)
00354 {
00355    switch ( mem_test_unit_ready(usb_LUN) )
00356    {
00357       case CTRL_GOOD :
00358       sbc_lun_status_is_good();
00359       break;
00360 
00361       case CTRL_NO_PRESENT :
00362       sbc_lun_status_is_not_present();
00363       break;
00364 
00365       case CTRL_BUSY :
00366       sbc_lun_status_is_busy_or_change();
00367       break;
00368 
00369       case CTRL_FAIL :
00370       default :
00371       sbc_lun_status_is_fail();
00372       break;
00373    }
00374    return TRUE;
00375 }
00376 
00377 
00378 Bool sbc_read_capacity (void)
00379 {
00380    U32 mem_size_nb_sector;
00381 
00382    switch ( mem_read_capacity( usb_LUN, &mem_size_nb_sector ) )
00383    {
00384       case CTRL_GOOD :
00385       Usb_write_byte(MSB0(mem_size_nb_sector));    // return nb block
00386       Usb_write_byte(MSB1(mem_size_nb_sector));
00387       Usb_write_byte(MSB2(mem_size_nb_sector));
00388       Usb_write_byte(MSB3(mem_size_nb_sector));
00389       Usb_write_byte( 0               );           // return block size (= 512B)
00390       Usb_write_byte( 0               );
00391       Usb_write_byte( (U8)(512 >> 8)  );
00392       Usb_write_byte( (U8)(512 & 0xFF));
00393 
00394       Sbc_valid_write_usb(SBC_READ_CAPACITY_LENGTH);
00395       sbc_lun_status_is_good();
00396       return TRUE;
00397       break;
00398 
00399       case CTRL_NO_PRESENT :
00400       sbc_lun_status_is_not_present();
00401       break;
00402 
00403       case CTRL_BUSY :
00404       sbc_lun_status_is_busy_or_change();
00405       break;
00406 
00407       case CTRL_FAIL :
00408       default :
00409       sbc_lun_status_is_fail();
00410       break;
00411    }
00412    return FALSE;
00413 }
00414 
00415 
00416 Bool sbc_read_10 (void)
00417 {
00418    U32   mass_addr;                       // rd or wr block address
00419    U16   mass_size;                       // rd or write nb of blocks
00420 
00421    MSB0(mass_addr) = g_scsi_command[2];   // read address
00422    MSB1(mass_addr) = g_scsi_command[3];
00423    MSB2(mass_addr) = g_scsi_command[4];
00424    MSB3(mass_addr) = g_scsi_command[5];
00425 
00426    MSB(mass_size) = g_scsi_command[7];    // read size
00427    LSB(mass_size) = g_scsi_command[8];
00428    
00429    if( Is_usb_ms_data_direction_out() )
00430    {
00431       sbc_lun_status_is_cdb_field();
00432       return FALSE;
00433    }
00434    if( 0 == g_scsi_data_remaining )
00435    {
00436       if( mass_size == (g_scsi_data_remaining/512) )
00437       {
00438          sbc_lun_status_is_good();
00439       }else{
00440          sbc_lun_status_is_cdb_field();
00441       }
00442       return TRUE;
00443    }
00444 
00445    switch ( memory_2_usb( usb_LUN , mass_addr,  g_scsi_data_remaining/512 ) )
00446    {
00447       case CTRL_GOOD :
00448       if( mass_size == (g_scsi_data_remaining/512) )
00449       {
00450          sbc_lun_status_is_good();
00451       }else{
00452          sbc_lun_status_is_cdb_field();
00453       }
00454       g_scsi_data_remaining = 0;
00455       break;
00456 
00457       case CTRL_NO_PRESENT :
00458       sbc_lun_status_is_not_present();
00459       return FALSE;
00460       break;
00461 
00462       case CTRL_BUSY :
00463       sbc_lun_status_is_busy_or_change();
00464       return FALSE;
00465       break;
00466 
00467       case CTRL_FAIL :
00468       default :
00469       sbc_lun_status_is_fail();
00470       return FALSE;
00471       break;
00472    }
00473    return TRUE;
00474 }
00475 
00476 
00477 Bool sbc_write_10 (void)
00478 {
00479    U32   mass_addr;                       // rd or wr block address
00480    U16   mass_size;                       // rd or write nb of blocks
00481 
00482    MSB0(mass_addr) = g_scsi_command[2];   // read address
00483    MSB1(mass_addr) = g_scsi_command[3];
00484    MSB2(mass_addr) = g_scsi_command[4];
00485    MSB3(mass_addr) = g_scsi_command[5];
00486 
00487    MSB(mass_size) = g_scsi_command[7];    // read size
00488    LSB(mass_size) = g_scsi_command[8];
00489    
00490    if( Is_usb_ms_data_direction_in() )
00491    {
00492       sbc_lun_status_is_cdb_field();
00493       return FALSE;
00494    }
00495 
00496    if( 0 == g_scsi_data_remaining )
00497    {
00498       if( mass_size == (g_scsi_data_remaining/512) )
00499       {
00500          sbc_lun_status_is_good();
00501       }else{
00502          sbc_lun_status_is_cdb_field();
00503       }
00504       return TRUE;
00505    }
00506    
00507    if( TRUE == mem_wr_protect( usb_LUN ) )
00508    {
00509       sbc_lun_status_is_protected();
00510       return FALSE;
00511    }
00512 
00513    switch (usb_2_memory( usb_LUN , mass_addr, g_scsi_data_remaining/512 ))
00514    {
00515       case CTRL_GOOD :
00516       if( mass_size == (g_scsi_data_remaining/512) )
00517       {
00518          sbc_lun_status_is_good();
00519       }else{
00520          sbc_lun_status_is_cdb_field();
00521       }
00522       g_scsi_data_remaining = 0;
00523       break;
00524 
00525       case CTRL_NO_PRESENT :
00526       sbc_lun_status_is_not_present();
00527       return FALSE;
00528       break;
00529 
00530       case CTRL_BUSY :
00531       sbc_lun_status_is_busy_or_change();
00532       return FALSE;
00533       break;
00534 
00535       case CTRL_FAIL :
00536       default :
00537       sbc_lun_status_is_fail();
00538       return FALSE;
00539       break;
00540    }
00541    return TRUE;
00542 }
00543 
00544 
00559 Bool sbc_mode_sense( Bool b_sense_10 )
00560 {
00561    U8 allocation_length;
00562 
00563    if( b_sense_10 )
00564       allocation_length = g_scsi_command[8];
00565    else
00566       allocation_length = g_scsi_command[4];
00567 
00568    // switch for page code
00569    switch ( g_scsi_command[2] & SBC_MSK_PAGE_CODE )
00570    {
00571       case SBC_PAGE_CODE_INFORMATIONAL_EXCEPTIONS:
00572       sbc_header_mode_sense( b_sense_10 , SBC_MODE_DATA_LENGTH_INFORMATIONAL_EXCEPTIONS );
00573       send_informational_exceptions_page();
00574       Sbc_valid_write_usb(SBC_MODE_DATA_LENGTH_INFORMATIONAL_EXCEPTIONS + 1);
00575       break;
00576 
00577       case SBC_PAGE_CODE_READ_WRITE_ERROR_RECOVERY:
00578       sbc_header_mode_sense( b_sense_10 , SBC_MODE_DATA_LENGTH_READ_WRITE_ERROR_RECOVERY );
00579       send_read_write_error_recovery_page(allocation_length);
00580       Sbc_valid_write_usb(SBC_MODE_DATA_LENGTH_READ_WRITE_ERROR_RECOVERY + 1);
00581       break;
00582 
00583       case SBC_PAGE_CODE_ALL:
00584       if( b_sense_10 ) {
00585          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 );
00586       }else{
00587          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 );
00588       }
00589       if( b_sense_10 )
00590       {
00591          if (allocation_length == 8)
00592          {
00593             Sbc_valid_write_usb(8);
00594             break;
00595          }
00596       }
00597       else
00598       {
00599          if (allocation_length == 4)
00600          {
00601             Sbc_valid_write_usb(4);
00602             break;
00603          }
00604       }
00605       // send page by ascending order code
00606       send_read_write_error_recovery_page(allocation_length);  // 12 bytes
00607       if (allocation_length > 12)
00608       {
00609          send_informational_exceptions_page();                 // 12 bytes
00610          Sbc_valid_write_usb(SBC_MODE_DATA_LENGTH_CODE_ALL + 1);
00611       }
00612       else
00613       {
00614          Sbc_valid_write_usb(allocation_length);
00615       }
00616       break;
00617 
00618       default:
00619       sbc_lun_status_is_cdb_field();
00620       return FALSE;
00621       break;
00622    }
00623    sbc_lun_status_is_good();
00624    return TRUE;
00625 }
00626 
00627 
00635 void sbc_header_mode_sense( Bool b_sense_10 , U8 u8_data_length )
00636 {
00637    // Send Data length
00638    if( b_sense_10 )
00639    {
00640       Usb_write_byte(0);
00641    }
00642    Usb_write_byte( u8_data_length );
00643 
00644    // Send device type
00645    Usb_write_byte(SBC_MEDIUM_TYPE);
00646 
00647    // Write protect status
00648    if (mem_wr_protect( usb_LUN ))
00649    {
00650       Usb_write_byte(SBC_DEV_SPEC_PARAM_WR_PROTECT);  // Device is write protected
00651    }
00652    else
00653    {
00654       Usb_write_byte(SBC_DEV_SPEC_PARAM_WR_ENABLE);   // Device is write enabled
00655    }
00656 
00657    if( b_sense_10 )
00658    {  // Reserved
00659       Usb_write_byte(0);
00660       Usb_write_byte(0);
00661    }
00662 
00663    // Send Block descriptor length
00664    if( b_sense_10 )
00665    {
00666       Usb_write_byte(0);
00667    }
00668    Usb_write_byte(SBC_BLOCK_DESCRIPTOR_LENGTH);
00669 }
00670 
00671 
00683 void send_informational_exceptions_page (void)
00684 {
00685    Usb_write_byte(SBC_PAGE_CODE_INFORMATIONAL_EXCEPTIONS);     // Page Code: Informational exceptions control page
00686                                                                // See chapter 8.3.8 on SPC-2 specification
00687    Usb_write_byte(SBC_PAGE_LENGTH_INFORMATIONAL_EXCEPTIONS);   // Page Length
00688    Usb_write_byte(0x00);                                       // ..., Test bit = 0, ...
00689    Usb_write_byte(SBC_MRIE);                                   // MRIE = 0x05
00690    Usb_write_byte(0x00);                                       // Interval Timer (MSB)
00691    Usb_write_byte(0x00);
00692    Usb_write_byte(0x00);
00693    Usb_write_byte(0x00);                                       // Interval Timer (LSB)
00694    Usb_write_byte(0x00);                                       // Report Count (MSB)
00695    Usb_write_byte(0x00);
00696    Usb_write_byte(0x00);
00697    Usb_write_byte(0x01);                                       // Report Count (LSB)
00698 }
00699 
00700 
00712 void send_read_write_error_recovery_page (U8 length)
00713 {
00714    Usb_write_byte(SBC_PAGE_CODE_READ_WRITE_ERROR_RECOVERY);
00715 
00716    Usb_write_byte(SBC_PAGE_LENGTH_READ_WRITE_ERROR_RECOVERY);   // Page Length
00717    Usb_write_byte(0x80);
00718    Usb_write_byte(SBC_READ_RETRY_COUNT);
00719    Usb_write_byte(SBC_CORRECTION_SPAN);
00720    Usb_write_byte(SBC_HEAD_OFFSET_COUNT);
00721    Usb_write_byte(SBC_DATA_STROBE_OFFSET);
00722    Usb_write_byte(0x00);   // Reserved
00723 
00724    if (length > 12)
00725    {
00726       Usb_write_byte(SBC_WRITE_RETRY_COUNT);
00727       Usb_write_byte(0x00);
00728       Usb_write_byte(SBC_RECOVERY_LIMIT_MSB);
00729       Usb_write_byte(SBC_RECOVERY_LIMIT_LSB);
00730    }
00731 }
00732 
00748 Bool sbc_prevent_allow_medium_removal(void)
00749 {
00750    sbc_lun_status_is_good();
00751    return TRUE;
00752 }
00753 
00754 
00757 void sbc_lun_status_is_good(void)
00758 {
00759    Sbc_send_good();
00760    Sbc_build_sense(SBC_SENSE_KEY_NO_SENSE, SBC_ASC_NO_ADDITIONAL_SENSE_INFORMATION, 0x00);
00761 }
00762 
00765 void sbc_lun_status_is_not_present(void)
00766 {
00767    Sbc_send_failed();
00768    Sbc_build_sense(SBC_SENSE_KEY_NOT_READY, SBC_ASC_MEDIUM_NOT_PRESENT, 0x00);
00769 }
00770 
00773 void sbc_lun_status_is_busy_or_change(void)
00774 {
00775    Sbc_send_failed();
00776    Sbc_build_sense(SBC_SENSE_KEY_UNIT_ATTENTION, SBC_ASC_NOT_READY_TO_READY_CHANGE, 0x00 );
00777 }
00778 
00781 void sbc_lun_status_is_fail(void)
00782 {
00783    Sbc_send_failed();
00784    Sbc_build_sense(SBC_SENSE_KEY_HARDWARE_ERROR, SBC_ASC_NO_ADDITIONAL_SENSE_INFORMATION, 0x00);
00785 }
00786 
00789 void sbc_lun_status_is_protected(void)
00790 {
00791    Sbc_send_failed();
00792    Sbc_build_sense(SBC_SENSE_KEY_DATA_PROTECT, SBC_ASC_WRITE_PROTECTED, 0x00);
00793 }
00794 
00797 void sbc_lun_status_is_cdb_field(void)
00798 {
00799    Sbc_send_failed();
00800    Sbc_build_sense(SBC_SENSE_KEY_ILLEGAL_REQUEST, SBC_ASC_INVALID_FIELD_IN_CDB, 0x00);
00801 }
00802 

Generated on Fri Sep 11 14:39:51 2009 for ATMEL by  doxygen 1.5.3