Contiki 2.6
|
00001 /* This file has been prepared for Doxygen automatic documentation generation.*/ 00002 /*! \file scsi_decoder.c ******************************************************* 00003 * 00004 * \brief 00005 * This file is the scsi decoder 00006 * 00007 * \addtogroup usbstick 00008 * 00009 * \author 00010 * Atmel Corporation: http://www.atmel.com \n 00011 * Support email: avr@atmel.com 00012 ******************************************************************************/ 00013 /* 00014 Copyright (c) 2004 ATMEL Corporation 00015 All rights reserved. 00016 00017 Redistribution and use in source and binary forms, with or without 00018 modification, are permitted provided that the following conditions are met: 00019 00020 * Redistributions of source code must retain the above copyright 00021 notice, this list of conditions and the following disclaimer. 00022 * Redistributions in binary form must reproduce the above copyright 00023 notice, this list of conditions and the following disclaimer in 00024 the documentation and/or other materials provided with the 00025 distribution. 00026 * Neither the name of the copyright holders nor the names of 00027 contributors may be used to endorse or promote products derived 00028 from this software without specific prior written permission. 00029 00030 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00031 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00032 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00033 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 00034 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00035 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00036 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00037 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00038 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00039 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00040 POSSIBILITY OF SUCH DAMAGE. 00041 */ 00042 00043 /** 00044 \addtogroup usbstorage 00045 @{ 00046 */ 00047 00048 //_____ I N C L U D E S ___________________________________________________ 00049 00050 #include "config.h" 00051 #include "storage/scsi_decoder.h" 00052 #include "conf_usb.h" 00053 #include "usb_drv.h" 00054 #include "storage/ctrl_status.h" 00055 #include "storage/ctrl_access.h" 00056 00057 00058 //_____ M A C R O S ________________________________________________________ 00059 00060 00061 //_____ D E F I N I T I O N S ______________________________________________ 00062 00063 00064 U8 g_scsi_command[16]; 00065 U8 g_scsi_status; 00066 U32 g_scsi_data_remaining; 00067 00068 FLASH U8 g_sbc_vendor_id[8] = SBC_VENDOR_ID; 00069 FLASH U8 g_sbc_product_id[16] = SBC_PRODUCT_ID; 00070 FLASH U8 g_sbc_revision_id[4] = SBC_REVISION_ID; 00071 00072 extern U8 usb_LUN; 00073 00074 s_scsi_sense g_scsi_sense; 00075 00076 00077 FLASH struct sbc_st_std_inquiry_data sbc_std_inquiry_data = 00078 { 00079 /* Byte 0 : 0x00 */ 00080 0x00, /* DeviceType: Direct-access device */ 00081 0, /* PeripheralQualifier : Currently connected */ 00082 00083 /* Byte 1 : 0x80 */ 00084 0, /* Reserved1 */ 00085 1, /* RMB : Medium is removable (this bit must be at 1, else the medium isn't see on Windows) */ 00086 00087 // /* Byte 2 : 0x02 */ 00088 // 0x02, /* Version: Device compliant to ANSI X3.131:1994 */ 00089 00090 /* Byte 2 : 0x00 */ 00091 0x00, /* Version: Device not compliant to any standard */ 00092 00093 /* Byte 3 : 0x02 */ 00094 2, /* Response data format */ 00095 0, /* NormACA */ 00096 0, /* Obsolete0 */ 00097 0, /* AERC */ 00098 00099 /* Byte 4 : 0x1F */ 00100 /* Byte 5 : 0x00 */ 00101 /* Byte 6 : 0x00 */ 00102 /* Reserved4[3] */ 00103 { 00104 0x1F, /* Additional Length (n-4) */ 00105 0, /* SCCS : SCC supported */ 00106 0 00107 }, 00108 00109 /* Byte 7 : 0x00 */ 00110 0, /* SoftReset */ 00111 0, /* CommandQueue */ 00112 0, /* Reserved5 */ 00113 0, /* LinkedCommands */ 00114 0, /* Synchronous */ 00115 0, /* Wide16Bit */ 00116 0, /* Wide32Bit */ 00117 0, /* RelativeAddressing */ 00118 }; 00119 00120 00121 static void send_informational_exceptions_page (void); 00122 static void send_read_write_error_recovery_page (U8); 00123 static void sbc_header_mode_sense( Bool b_sense_10 , U8 u8_data_length ); 00124 00125 00126 //_____ D E C L A R A T I O N S ____________________________________________ 00127 /** 00128 * @brief SCSI decoder function 00129 * 00130 * This function read the SCSI command and launches the appropriate function 00131 * 00132 * @warning Code:.. bytes (function FLASH length) 00133 * 00134 * @return FALSE: result KO, 00135 * TRUE: result OK 00136 * 00137 */ 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]) /* check other command received */ 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 case SBC_CMD_MODE_SENSE_10: /* 0x5A - Optional */ 00187 return sbc_mode_sense( TRUE ); 00188 break; 00189 00190 case SBC_CMD_FORMAT_UNIT: /* 0x04 - Mandatory */ 00191 00192 case SBC_CMD_MODE_SELECT_6: /* 0x15 - Optional */ 00193 00194 00195 00196 00197 case SBC_CMD_START_STOP_UNIT: /* 0x1B - Optional */ 00198 case SBC_CMD_SEND_DIAGNOSTIC: /* 0x1D - */ 00199 case SBC_CMD_READ_LONG: /* 0x23 - Optional */ 00200 case SBC_CMD_SYNCHRONIZE_CACHE: /* 0x35 - Optional */ 00201 case SBC_CMD_WRITE_BUFFER: /* 0x3B - Optional */ 00202 case SBC_CMD_RESERVE_10: /* 0x56 - Mandatory */ 00203 case SBC_CMD_RELEASE_10: /* 0x57 - Mandatory - see chapter 7.16 - SPC 2 */ 00204 default: 00205 { /* Command not supported */ 00206 Sbc_send_failed(); 00207 Sbc_build_sense(SBC_SENSE_KEY_ILLEGAL_REQUEST, SBC_ASC_INVALID_COMMAND_OPERATION_CODE, 0x00); 00208 return FALSE; 00209 break; 00210 } 00211 } 00212 return TRUE; 00213 } 00214 00215 00216 /** 00217 * @brief This function manages the SCSI REQUEST SENSE command (0x03) 00218 * 00219 * The SCSI Sense contains the status of the last command 00220 * This status is composed of 3 Bytes : 00221 * - sense key (g_scsi_sense.key) 00222 * - additional sense code (g_scsi_sense.asc) 00223 * - additional sense code qualifier (g_scsi_sense.ascq) 00224 * 00225 * @warning Code:.. bytes (function code length) 00226 * 00227 * @return FALSE: result KO, 00228 * TRUE: result OK 00229 * 00230 */ 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 00238 /* Initialize the request sense data */ 00239 request_sens_output[0] = SBC_RESPONSE_CODE_SENSE; /* 70h */ 00240 request_sens_output[1] = 0x00; /* Obsolete */ 00241 request_sens_output[2] = g_scsi_sense.key; 00242 00243 request_sens_output[3] = 0x00; /* For direct access media, Information field */ 00244 request_sens_output[4] = 0x00; /* give the unsigned logical block */ 00245 request_sens_output[5] = 0x00; /* address associated with the sense key */ 00246 request_sens_output[6] = 0x00; 00247 00248 request_sens_output[7] = SBC_ADDITIONAL_SENSE_LENGTH; /* !! UFI device shall not adjust the Additional sense length to reflect truncation */ 00249 request_sens_output[8] = SBC_COMMAND_SPECIFIC_INFORMATION_3; 00250 request_sens_output[9] = SBC_COMMAND_SPECIFIC_INFORMATION_2; 00251 request_sens_output[10] = SBC_COMMAND_SPECIFIC_INFORMATION_1; 00252 request_sens_output[11] = SBC_COMMAND_SPECIFIC_INFORMATION_0; 00253 00254 request_sens_output[12] = g_scsi_sense.asc; 00255 request_sens_output[13] = g_scsi_sense.ascq; 00256 00257 request_sens_output[14] = SBC_FIELD_REPLACEABLE_UNIT_CODE; 00258 request_sens_output[15] = SBC_SENSE_KEY_SPECIFIC_2; 00259 request_sens_output[16] = SBC_SENSE_KEY_SPECIFIC_1; 00260 request_sens_output[17] = SBC_SENSE_KEY_SPECIFIC_0; 00261 00262 /* Send the request data */ 00263 for( i=0 ; i<allocation_length ; i++ ) 00264 { 00265 Usb_write_byte( request_sens_output[i] ); 00266 } 00267 Sbc_valid_write_usb( allocation_length ); 00268 00269 sbc_lun_status_is_good(); 00270 00271 return TRUE; 00272 } 00273 00274 /** 00275 * @brief This function manages the SCSI INQUIRY command (0x12) 00276 * 00277 * The SCSI Inquiry field contains information regarding parameters 00278 * of the target. For example: 00279 * - vendor identification 00280 * - product identification 00281 * - peripheral qualifier 00282 * - peripheral device type 00283 * - etc 00284 * 00285 * @warning Code:.. bytes (function code length) 00286 * 00287 * @return FALSE: result KO, 00288 * TRUE: result OK 00289 * 00290 */ 00291 Bool sbc_inquiry (void) 00292 { 00293 U8 allocation_length, i; 00294 00295 #ifdef AVRGCC 00296 PGM_VOID_P ptr; 00297 #else 00298 U8 FLASH *ptr; 00299 #endif 00300 00301 if( (0 == (g_scsi_command[1] & 0x03) ) // CMDT and EPVD bits are 0 00302 && (0 == g_scsi_command[2] ) ) // PAGE or OPERATION CODE fields = 0x00? 00303 { 00304 //** send standard inquiry data 00305 00306 // Check the size of inquiry data 00307 allocation_length = g_scsi_command[4]; 00308 if (allocation_length > SBC_MAX_INQUIRY_DATA) 00309 { 00310 allocation_length = SBC_MAX_INQUIRY_DATA; 00311 } 00312 00313 // send first inquiry data (0 to 8) 00314 ptr = (FLASH U8*) &sbc_std_inquiry_data; 00315 00316 for ( i=0 ; ((i != 36) && (allocation_length > i)); i++) 00317 { 00318 if( 8 == i ) 00319 { // send vendor id (8 to 16) 00320 ptr = (FLASH U8 *) &g_sbc_vendor_id; 00321 } 00322 if( 16 == i ) 00323 { // send product id (16 to 32) 00324 ptr = (FLASH U8 *) &g_sbc_product_id; 00325 } 00326 if( 32 == i ) 00327 { // send revision id (32 to 36) 00328 ptr = (FLASH U8 *) &g_sbc_revision_id; 00329 } 00330 #ifndef AVRGCC 00331 Usb_write_byte((U8)(*ptr++)); // send tab 00332 #else // AVRGCC does not support point to PGM space 00333 #warning with avrgcc assumes devices descriptors are stored in the lower 64Kbytes of on-chip flash memory 00334 Usb_write_byte(pgm_read_byte_near((unsigned int)ptr++)); 00335 #endif 00336 00337 } 00338 00339 // send data (36 to SBC_MAX_INQUIRY_DATA), and can be tranmitted by Bulk 00340 // Description of next bytes (this bytes is always egal to 0) : 00341 // VendorSpecific : 20 Bytes 00342 // Next byte : 1 byte 00343 // - InfoUnitSupport : 1 bit 00344 // - QuickArbitSupport : 1 bit 00345 // - Clocking : 2 bits 00346 // - Reserved6 : 4 bits 00347 // Reserved7 : 1 byte 00348 // VersionDescriptor : 8 bytes 00349 // Reserved8 : 22 bytes 00350 // ... 00351 while( allocation_length > i ) 00352 { 00353 if (64 == i) 00354 { // for each 64 bytes, send USB packet 00355 Sbc_valid_write_usb(64); 00356 allocation_length -= 64; 00357 i = 0; 00358 } 00359 Usb_write_byte(0); // write value of last bytes of inquiry data 00360 i++; 00361 } 00362 // send last USB packet 00363 Sbc_valid_write_usb(allocation_length); 00364 sbc_lun_status_is_good(); 00365 return TRUE; 00366 } 00367 else 00368 { // (CMDT=EVPD <> 0) or (PAGE CODE <> 0x00) 00369 Sbc_send_failed(); 00370 Sbc_build_sense(SBC_SENSE_KEY_ILLEGAL_REQUEST, SBC_ASC_INVALID_FIELD_IN_CDB, 0x00); 00371 return FALSE; 00372 } 00373 } 00374 00375 00376 Bool sbc_test_unit_ready(void) 00377 { 00378 switch ( mem_test_unit_ready(usb_LUN) ) 00379 { 00380 case CTRL_GOOD : 00381 sbc_lun_status_is_good(); 00382 break; 00383 00384 case CTRL_NO_PRESENT : 00385 sbc_lun_status_is_not_present(); 00386 break; 00387 00388 case CTRL_BUSY : 00389 sbc_lun_status_is_busy_or_change(); 00390 break; 00391 00392 case CTRL_FAIL : 00393 default : 00394 sbc_lun_status_is_fail(); 00395 break; 00396 } 00397 return TRUE; 00398 } 00399 00400 00401 Bool sbc_read_capacity (void) 00402 { 00403 _MEM_TYPE_SLOW_ U32 mem_size_nb_sector; 00404 00405 switch ( mem_read_capacity( usb_LUN, &mem_size_nb_sector ) ) 00406 { 00407 case CTRL_GOOD : 00408 Usb_write_byte(MSB0(mem_size_nb_sector)); // return nb block 00409 Usb_write_byte(MSB1(mem_size_nb_sector)); 00410 Usb_write_byte(MSB2(mem_size_nb_sector)); 00411 Usb_write_byte(MSB3(mem_size_nb_sector)); 00412 Usb_write_byte( 0 ); // return block size (= 512B) 00413 Usb_write_byte( 0 ); 00414 Usb_write_byte( (U8)(512 >> 8) ); 00415 Usb_write_byte( (U8)(512 & 0xFF)); 00416 00417 Sbc_valid_write_usb(SBC_READ_CAPACITY_LENGTH); 00418 sbc_lun_status_is_good(); 00419 return TRUE; 00420 break; 00421 00422 case CTRL_NO_PRESENT : 00423 sbc_lun_status_is_not_present(); 00424 break; 00425 00426 case CTRL_BUSY : 00427 sbc_lun_status_is_busy_or_change(); 00428 break; 00429 00430 case CTRL_FAIL : 00431 default : 00432 sbc_lun_status_is_fail(); 00433 break; 00434 } 00435 return FALSE; 00436 } 00437 00438 00439 Bool sbc_read_10 (void) 00440 { 00441 U32 mass_addr; // rd or wr block address 00442 U16 mass_size; // rd or write nb of blocks 00443 00444 MSB0(mass_addr) = g_scsi_command[2]; // read address 00445 MSB1(mass_addr) = g_scsi_command[3]; 00446 MSB2(mass_addr) = g_scsi_command[4]; 00447 MSB3(mass_addr) = g_scsi_command[5]; 00448 00449 MSB(mass_size) = g_scsi_command[7]; // read size 00450 LSB(mass_size) = g_scsi_command[8]; 00451 00452 if (mass_size != 0) 00453 { 00454 switch ( memory_2_usb( usb_LUN , mass_addr, mass_size ) ) 00455 { 00456 case CTRL_GOOD : 00457 sbc_lun_status_is_good(); 00458 g_scsi_data_remaining = g_scsi_data_remaining - (512 * (Uint32)mass_size); 00459 return TRUE; 00460 break; 00461 00462 case CTRL_NO_PRESENT : 00463 sbc_lun_status_is_not_present(); 00464 return FALSE; 00465 break; 00466 00467 case CTRL_BUSY : 00468 sbc_lun_status_is_busy_or_change(); 00469 return FALSE; 00470 break; 00471 00472 case CTRL_FAIL : 00473 default : 00474 sbc_lun_status_is_fail(); 00475 return FALSE; 00476 break; 00477 } 00478 } 00479 else 00480 { // No data to transfer 00481 sbc_lun_status_is_good(); 00482 } 00483 return TRUE; 00484 } 00485 00486 00487 Bool sbc_write_10 (void) 00488 { 00489 U32 mass_addr; // rd or wr block address 00490 U16 mass_size; // rd or write nb of blocks 00491 00492 MSB0(mass_addr) = g_scsi_command[2]; // read address 00493 MSB1(mass_addr) = g_scsi_command[3]; 00494 MSB2(mass_addr) = g_scsi_command[4]; 00495 MSB3(mass_addr) = g_scsi_command[5]; 00496 00497 MSB(mass_size) = g_scsi_command[7]; // read size 00498 LSB(mass_size) = g_scsi_command[8]; 00499 00500 if (mass_size != 0) 00501 { 00502 if( TRUE == mem_wr_protect( usb_LUN ) ) 00503 { 00504 sbc_lun_status_is_protected(); 00505 return FALSE; 00506 #warning For Win98 data must be read to avoid blocking 00507 } 00508 else 00509 { 00510 switch (usb_2_memory( usb_LUN , mass_addr, mass_size )) 00511 { 00512 case CTRL_GOOD : 00513 sbc_lun_status_is_good(); 00514 g_scsi_data_remaining = g_scsi_data_remaining - (512 * (Uint32)mass_size); 00515 return TRUE; 00516 break; 00517 00518 case CTRL_NO_PRESENT : 00519 sbc_lun_status_is_not_present(); 00520 return FALSE; 00521 break; 00522 00523 case CTRL_BUSY : 00524 sbc_lun_status_is_busy_or_change(); 00525 return FALSE; 00526 break; 00527 00528 case CTRL_FAIL : 00529 default : 00530 sbc_lun_status_is_fail(); 00531 return FALSE; 00532 break; 00533 } 00534 } 00535 } 00536 else 00537 { // No data to transfer 00538 sbc_lun_status_is_good(); 00539 } 00540 return TRUE; 00541 } 00542 00543 00544 /** 00545 * @brief This function manages the SCSI MODE SENSE command (0x1A for sense 6 and 0x5A for sense 10) 00546 * 00547 * The SCSI mode sense function returns parameters to an application client. 00548 * It is a complementary command to the SCSI MODE SELECT command. 00549 * 00550 * @warning Code:.. bytes (function code length) 00551 * 00552 * @param b_sense_10 ( TRUE = sense 10, TRUE = sense 6) 00553 * 00554 * @return FALSE: result KO, 00555 * TRUE: result OK 00556 * 00557 */ 00558 Bool sbc_mode_sense( Bool b_sense_10 ) 00559 { 00560 U8 allocation_length; 00561 00562 if( b_sense_10 ) 00563 allocation_length = g_scsi_command[8]; 00564 else 00565 allocation_length = g_scsi_command[4]; 00566 00567 // switch for page code 00568 switch ( g_scsi_command[2] & SBC_MSK_PAGE_CODE ) 00569 { 00570 case SBC_PAGE_CODE_INFORMATIONAL_EXCEPTIONS: /* Page Code: Informational exceptions control page */ 00571 sbc_header_mode_sense( b_sense_10 , SBC_MODE_DATA_LENGTH_INFORMATIONAL_EXCEPTIONS ); 00572 send_informational_exceptions_page(); 00573 Sbc_valid_write_usb(SBC_MODE_DATA_LENGTH_INFORMATIONAL_EXCEPTIONS + 1); 00574 break; 00575 00576 case SBC_PAGE_CODE_READ_WRITE_ERROR_RECOVERY: 00577 sbc_header_mode_sense( b_sense_10 , SBC_MODE_DATA_LENGTH_READ_WRITE_ERROR_RECOVERY ); 00578 send_read_write_error_recovery_page(allocation_length); 00579 Sbc_valid_write_usb(SBC_MODE_DATA_LENGTH_READ_WRITE_ERROR_RECOVERY + 1); 00580 break; 00581 00582 case SBC_PAGE_CODE_ALL: 00583 sbc_header_mode_sense( b_sense_10 , SBC_MODE_DATA_LENGTH_CODE_ALL ); 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_send_failed(); 00615 Sbc_build_sense(SBC_SENSE_KEY_ILLEGAL_REQUEST, SBC_ASC_INVALID_FIELD_IN_CDB, 0x00); 00616 return FALSE; 00617 break; 00618 } 00619 sbc_lun_status_is_good(); 00620 return TRUE; 00621 } 00622 00623 00624 /** 00625 * @brief This function send the header of the SCSI MODE SENSE command 00626 * 00627 * @param b_sense_10 TRUE = sense 10, FALSE = sense 6 00628 * @param u8_data_length data length in byte 00629 * 00630 */ 00631 void sbc_header_mode_sense( Bool b_sense_10 , U8 u8_data_length ) 00632 { 00633 // Send Data length 00634 if( b_sense_10 ) 00635 { 00636 Usb_write_byte(0); 00637 } 00638 Usb_write_byte( u8_data_length ); 00639 00640 // Send device type 00641 Usb_write_byte(SBC_MEDIUM_TYPE); 00642 00643 // Write protect status 00644 if (mem_wr_protect( usb_LUN )) 00645 { 00646 Usb_write_byte(SBC_DEV_SPEC_PARAM_WR_PROTECT); // Device is write protected 00647 } 00648 else 00649 { 00650 Usb_write_byte(SBC_DEV_SPEC_PARAM_WR_ENABLE); // Device is write enabled 00651 } 00652 00653 if( b_sense_10 ) 00654 { // Reserved 00655 Usb_write_byte(0); 00656 Usb_write_byte(0); 00657 } 00658 00659 // Send Block descriptor length 00660 if( b_sense_10 ) 00661 { 00662 Usb_write_byte(0); 00663 } 00664 Usb_write_byte(SBC_BLOCK_DESCRIPTOR_LENGTH); 00665 } 00666 00667 00668 /** 00669 * @brief This function writes informational exceptions page parameters 00670 * 00671 * @warning Code:.. bytes (function code length) 00672 * 00673 * @return FALSE: result KO, 00674 * TRUE: result OK 00675 * 00676 */ 00677 void send_informational_exceptions_page (void) 00678 { 00679 Usb_write_byte(SBC_PAGE_CODE_INFORMATIONAL_EXCEPTIONS); /* Page Code: Informational exceptions control page */ 00680 /* See chapter 8.3.8 on SPC-2 specification */ 00681 Usb_write_byte(SBC_PAGE_LENGTH_INFORMATIONAL_EXCEPTIONS); /* Page Length */ 00682 Usb_write_byte(0x00); /* ..., Test bit = 0, ... */ 00683 Usb_write_byte(SBC_MRIE); /* MRIE = 0x05 */ 00684 Usb_write_byte(0x00); /* Interval Timer (MSB) */ 00685 Usb_write_byte(0x00); 00686 Usb_write_byte(0x00); 00687 Usb_write_byte(0x00); /* Interval Timer (LSB) */ 00688 Usb_write_byte(0x00); /* Report Count (MSB) */ 00689 Usb_write_byte(0x00); 00690 Usb_write_byte(0x00); 00691 Usb_write_byte(0x01); /* Report Count (LSB) */ 00692 } 00693 00694 00695 /** 00696 * @brief This function writes error recovery page 00697 * 00698 * @warning Code:.. bytes (function code length) 00699 * 00700 * @param length The length of 00701 * 00702 * @return FALSE: result KO, 00703 * TRUE: result OK 00704 * 00705 */ 00706 void send_read_write_error_recovery_page (U8 length) 00707 { 00708 Usb_write_byte(SBC_PAGE_CODE_READ_WRITE_ERROR_RECOVERY); 00709 00710 Usb_write_byte(SBC_PAGE_LENGTH_READ_WRITE_ERROR_RECOVERY); /* Page Length */ 00711 Usb_write_byte(0x80); 00712 Usb_write_byte(SBC_READ_RETRY_COUNT); 00713 Usb_write_byte(SBC_CORRECTION_SPAN); 00714 Usb_write_byte(SBC_HEAD_OFFSET_COUNT); 00715 Usb_write_byte(SBC_DATA_STROBE_OFFSET); 00716 Usb_write_byte(0x00); /* Reserved */ 00717 00718 if (length > 12) 00719 { 00720 Usb_write_byte(SBC_WRITE_RETRY_COUNT); 00721 Usb_write_byte(0x00); 00722 Usb_write_byte(SBC_RECOVERY_LIMIT_MSB); 00723 Usb_write_byte(SBC_RECOVERY_LIMIT_LSB); 00724 } 00725 } 00726 00727 /** 00728 * @brief This function manages the SCSI PREVENT ALLOW MEDIUM REMOVAL 00729 * command (0x1E) 00730 * 00731 * The SCSI prevent allow medium removal command requests that the target 00732 * enable or disable the removal of the medium in the logical unit. 00733 * 00734 * @warning Code:.. bytes (function code length) 00735 * 00736 * @return FALSE: result KO, 00737 * TRUE: result OK 00738 * 00739 */ 00740 Bool sbc_prevent_allow_medium_removal(void) 00741 { 00742 sbc_lun_status_is_good(); 00743 return TRUE; 00744 } 00745 00746 00747 //! This fonction send the UFI status GOOD 00748 //! 00749 void sbc_lun_status_is_good(void) 00750 { 00751 Sbc_send_good(); 00752 Sbc_build_sense(SBC_SENSE_KEY_NO_SENSE, SBC_ASC_NO_ADDITIONAL_SENSE_INFORMATION, 0x00); 00753 } 00754 00755 //! This fonction send the UFI status "lun not present" 00756 //! 00757 void sbc_lun_status_is_not_present(void) 00758 { 00759 Sbc_send_failed(); 00760 Sbc_build_sense(SBC_SENSE_KEY_NOT_READY, SBC_ASC_MEDIUM_NOT_PRESENT, 0x00); 00761 } 00762 00763 //! This fonction send the UFI status busy and change 00764 //! 00765 void sbc_lun_status_is_busy_or_change(void) 00766 { 00767 Sbc_send_failed(); 00768 Sbc_build_sense(SBC_SENSE_KEY_UNIT_ATTENTION, SBC_ASC_NOT_READY_TO_READY_CHANGE, 0x00 ); 00769 } 00770 00771 //! This fonction send the UFI status FAIL 00772 //! 00773 void sbc_lun_status_is_fail(void) 00774 { 00775 Sbc_send_failed(); 00776 Sbc_build_sense(SBC_SENSE_KEY_HARDWARE_ERROR, SBC_ASC_NO_ADDITIONAL_SENSE_INFORMATION, 0x00); 00777 } 00778 00779 //! This fonction send the UFI status FAIL because write protection 00780 //! 00781 void sbc_lun_status_is_protected(void) 00782 { 00783 Sbc_send_failed(); 00784 Sbc_build_sense(SBC_SENSE_KEY_DATA_PROTECT, SBC_ASC_WRITE_PROTECTED, 0x00); 00785 } 00786 00787 /** @} */