00001
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050 #include "conf_usb.h"
00051
00052
00053 #if USB_DEVICE_FEATURE == ENABLED
00054
00055 #include "scsi_decoder.h"
00056 #include "usb_drv.h"
00057 #include "ctrl_access.h"
00058
00059
00060
00061
00062 extern U8 usb_LUN;
00063 extern U8 ms_endpoint;
00064
00065
00074 static void sbc_header_mode_sense(Bool b_sense_10, U8 u8_data_length);
00075
00080 static void send_read_write_error_recovery_page(U8 length);
00081
00084 static void send_informational_exceptions_page(void);
00085
00086
00087
00088
00089 U8 g_scsi_command[16];
00090 U8 g_scsi_status;
00091 U32 g_scsi_data_remaining;
00092
00093 s_scsi_sense g_scsi_sense;
00094
00095 U8 g_scsi_ep_ms_in;
00096 U8 g_scsi_ep_ms_out;
00097
00099 static const sbc_st_std_inquiry_data sbc_std_inquiry_data =
00100 {
00101
00102 0,
00103 0,
00104
00105
00106 1,
00107 0,
00108
00109
00110 0,
00111
00112
00113 0,
00114 0,
00115 0,
00116 2,
00117
00118
00119
00120
00121
00122 {
00123 0x1F,
00124 0,
00125 0
00126 },
00127
00128
00129 0,
00130 0,
00131 0,
00132 0,
00133 0,
00134 0,
00135 0,
00136 0,
00137
00138 SBC_VENDOR_ID,
00139
00140 SBC_PRODUCT_ID,
00141
00142 SBC_REVISION_ID
00143 };
00144
00145
00146 Bool scsi_decode_command(void)
00147 {
00148 Bool status = FALSE;
00149
00150 switch (g_scsi_command[0])
00151 {
00152 case SBC_CMD_TEST_UNIT_READY:
00153 status = sbc_test_unit_ready();
00154 break;
00155
00156 case SBC_CMD_REQUEST_SENSE:
00157 status = sbc_request_sense();
00158 break;
00159
00160 case SBC_CMD_INQUIRY:
00161 status = sbc_inquiry();
00162 break;
00163
00164 case SBC_CMD_MODE_SENSE_6:
00165 status = sbc_mode_sense(FALSE);
00166 break;
00167
00168 case SBC_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
00169 status = sbc_prevent_allow_medium_removal();
00170 break;
00171
00172 case SBC_CMD_READ_CAPACITY_10:
00173 status = sbc_read_capacity();
00174 break;
00175
00176 case SBC_CMD_READ_10:
00177 Scsi_start_read_action();
00178 status = sbc_read_10();
00179 Scsi_stop_read_action();
00180 break;
00181
00182 case SBC_CMD_WRITE_10:
00183 Scsi_start_write_action();
00184 status = sbc_write_10();
00185 Scsi_stop_write_action();
00186 break;
00187
00188 case SBC_CMD_VERIFY_10:
00189 status = TRUE;
00190 sbc_lun_status_is_good();
00191 break;
00192
00193 case SBC_CMD_MODE_SENSE_10:
00194 status = sbc_mode_sense(TRUE);
00195 break;
00196
00197 case SBC_CMD_START_STOP_UNIT:
00198 break;
00199
00200 case SBC_CMD_FORMAT_UNIT:
00201 case SBC_CMD_REASSIGN_BLOCKS:
00202 case SBC_CMD_READ_6:
00203 case SBC_CMD_WRITE_6:
00204 case SBC_CMD_MODE_SELECT_6:
00205 case SBC_CMD_RECEIVE_DIAGNOSTIC_RESULTS:
00206 case SBC_CMD_SEND_DIAGNOSTIC:
00207 case SBC_CMD_WRITE_AND_VERIFY_10:
00208 case SBC_CMD_PREFETCH_10:
00209 case SBC_CMD_SYNCHRONIZE_CACHE_10:
00210 case SBC_CMD_READ_DEFECT_DATA_10:
00211 case SBC_CMD_WRITE_BUFFER:
00212 case SBC_CMD_READ_BUFFER:
00213 case SBC_CMD_READ_LONG_10:
00214 case SBC_CMD_WRITE_LONG_10:
00215 case SBC_CMD_WRITE_SAME_10:
00216 case SBC_CMD_LOG_SELECT:
00217 case SBC_CMD_LOG_SENSE:
00218 case SBC_CMD_XDWRITE_10:
00219 case SBC_CMD_XPWRITE_10:
00220 case SBC_CMD_XDREAD_10:
00221 case SBC_CMD_XDWRITEREAD_10:
00222 case SBC_CMD_MODE_SELECT_10:
00223 case SBC_CMD_PERSISTENT_RESERVE_IN:
00224 case SBC_CMD_PERSISTENT_RESERVE_OUT:
00225 case SBC_CMD_EXTENDED_COPY:
00226 case SBC_CMD_RECEIVE_COPY_RESULTS:
00227 case SBC_CMD_ACCESS_CONTROL_IN:
00228 case SBC_CMD_ACCESS_CONTROL_OUT:
00229 case SBC_CMD_READ_16:
00230 case SBC_CMD_WRITE_16:
00231 case SBC_CMD_READ_ATTRIBUTE:
00232 case SBC_CMD_WRITE_ATTRIBUTE:
00233 case SBC_CMD_WRITE_AND_VERIFY_16:
00234 case SBC_CMD_VERIFY_16:
00235 case SBC_CMD_PREFETCH_16:
00236 case SBC_CMD_SYNCHRONIZE_CACHE_16:
00237 case SBC_CMD_WRITE_SAME_16:
00238 case SBC_CMD_REPORT_LUNS:
00239 case SBC_CMD_READ_12:
00240 case SBC_CMD_WRITE_12:
00241 case SBC_CMD_WRITE_AND_VERIFY_12:
00242 case SBC_CMD_VERIFY_12:
00243 case SBC_CMD_READ_DEFECT_DATA_12:
00244 default:
00245
00246 Sbc_send_failed();
00247 Sbc_build_sense(SBC_SENSE_KEY_ILLEGAL_REQUEST, SBC_ASC_INVALID_COMMAND_OPERATION_CODE, 0x00);
00248 break;
00249 }
00250
00251 return status;
00252 }
00253
00254
00255 Bool sbc_test_unit_ready(void)
00256 {
00257 switch (mem_test_unit_ready(usb_LUN))
00258 {
00259 case CTRL_GOOD:
00260 sbc_lun_status_is_good();
00261 break;
00262
00263 case CTRL_NO_PRESENT:
00264 sbc_lun_status_is_not_present();
00265 break;
00266
00267 case CTRL_BUSY:
00268 sbc_lun_status_is_busy_or_change();
00269 break;
00270
00271 case CTRL_FAIL:
00272 default:
00273 sbc_lun_status_is_fail();
00274 break;
00275 }
00276
00277 return TRUE;
00278 }
00279
00280
00281 Bool sbc_request_sense(void)
00282 {
00283 U8 allocation_length;
00284 U8 request_sense_output[18];
00285
00286 allocation_length = min(g_scsi_command[4], sizeof(request_sense_output));
00287
00288 if( allocation_length != 0 )
00289 {
00290
00291 request_sense_output[ 0] = SBC_RESPONSE_CODE_SENSE;
00292 request_sense_output[ 1] = 0x00;
00293 request_sense_output[ 2] = g_scsi_sense.key;
00294
00295 request_sense_output[ 3] = 0x00;
00296 request_sense_output[ 4] = 0x00;
00297 request_sense_output[ 5] = 0x00;
00298 request_sense_output[ 6] = 0x00;
00299
00300 request_sense_output[ 7] = SBC_ADDITIONAL_SENSE_LENGTH;
00301 request_sense_output[ 8] = SBC_COMMAND_SPECIFIC_INFORMATION_3;
00302 request_sense_output[ 9] = SBC_COMMAND_SPECIFIC_INFORMATION_2;
00303 request_sense_output[10] = SBC_COMMAND_SPECIFIC_INFORMATION_1;
00304 request_sense_output[11] = SBC_COMMAND_SPECIFIC_INFORMATION_0;
00305
00306 request_sense_output[12] = g_scsi_sense.asc;
00307 request_sense_output[13] = g_scsi_sense.ascq;
00308
00309 request_sense_output[14] = SBC_FIELD_REPLACEABLE_UNIT_CODE;
00310 request_sense_output[15] = SBC_SENSE_KEY_SPECIFIC_2;
00311 request_sense_output[16] = SBC_SENSE_KEY_SPECIFIC_1;
00312 request_sense_output[17] = SBC_SENSE_KEY_SPECIFIC_0;
00313
00314
00315 Usb_reset_endpoint_fifo_access(g_scsi_ep_ms_in);
00316 usb_write_ep_txpacket(g_scsi_ep_ms_in, request_sense_output, allocation_length, NULL);
00317 Sbc_valid_write_usb(allocation_length);
00318
00319 while( 0 != Usb_nb_busy_bank(EP_MS_IN) );
00320 }
00321 sbc_lun_status_is_good();
00322 return (allocation_length == g_scsi_command[4]);
00323 }
00324
00325
00326 Bool sbc_inquiry(void)
00327 {
00328 U8 allocation_length;
00329
00330
00331 if ((g_scsi_command[1] & 0x03) || g_scsi_command[2])
00332 {
00333 sbc_lun_status_is_cdb_field();
00334 return FALSE;
00335 }
00336
00337
00338 allocation_length = min(g_scsi_command[4], sizeof(sbc_st_std_inquiry_data));
00339 if( allocation_length != 0 )
00340 {
00341 while (!Is_usb_in_ready(g_scsi_ep_ms_in))
00342 {
00343 if(!Is_usb_endpoint_enabled(g_scsi_ep_ms_in))
00344 return FALSE;
00345 }
00346 Usb_reset_endpoint_fifo_access(g_scsi_ep_ms_in);
00347 usb_write_ep_txpacket(g_scsi_ep_ms_in, &sbc_std_inquiry_data,
00348 allocation_length, NULL);
00349 Sbc_valid_write_usb(allocation_length);
00350
00351 while( 0 != Usb_nb_busy_bank(EP_MS_IN) );
00352 }
00353 sbc_lun_status_is_good();
00354 return (allocation_length == g_scsi_command[4]);
00355 }
00356
00357
00358 Bool sbc_mode_sense(Bool b_sense_10)
00359 {
00360 U8 allocation_length = (b_sense_10) ? g_scsi_command[8] : g_scsi_command[4];
00361
00362
00363 switch (g_scsi_command[2] & SBC_MSK_PAGE_CODE)
00364 {
00365 case SBC_PAGE_CODE_READ_WRITE_ERROR_RECOVERY:
00366 sbc_header_mode_sense(b_sense_10, SBC_MODE_DATA_LENGTH_READ_WRITE_ERROR_RECOVERY);
00367 send_read_write_error_recovery_page(allocation_length);
00368 Sbc_valid_write_usb(SBC_MODE_DATA_LENGTH_READ_WRITE_ERROR_RECOVERY + 1);
00369 break;
00370
00371
00372 case SBC_PAGE_CODE_INFORMATIONAL_EXCEPTIONS:
00373 sbc_header_mode_sense(b_sense_10, SBC_MODE_DATA_LENGTH_INFORMATIONAL_EXCEPTIONS);
00374 send_informational_exceptions_page();
00375 Sbc_valid_write_usb(SBC_MODE_DATA_LENGTH_INFORMATIONAL_EXCEPTIONS + 1);
00376 break;
00377
00378 case SBC_PAGE_CODE_ALL:
00379 if( b_sense_10 ) {
00380 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 );
00381 }else{
00382 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 );
00383 }
00384 if (allocation_length == ((b_sense_10) ? 8 : 4))
00385 {
00386 Sbc_valid_write_usb(allocation_length);
00387 break;
00388 }
00389
00390 send_read_write_error_recovery_page(allocation_length);
00391 if (allocation_length > 12)
00392 {
00393 send_informational_exceptions_page();
00394 Sbc_valid_write_usb(SBC_MODE_DATA_LENGTH_CODE_ALL + 1);
00395 }
00396 else
00397 {
00398 Sbc_valid_write_usb(allocation_length);
00399 }
00400 break;
00401
00402 default:
00403 sbc_lun_status_is_cdb_field();
00404 return FALSE;
00405 }
00406
00407 sbc_lun_status_is_good();
00408
00409 return TRUE;
00410 }
00411
00412
00413 Bool sbc_prevent_allow_medium_removal(void)
00414 {
00415 sbc_lun_status_is_good();
00416 return TRUE;
00417 }
00418
00419
00420 Bool sbc_read_capacity(void)
00421 {
00422 U32 mem_size_nb_sector;
00423
00424 switch (mem_read_capacity(usb_LUN, &mem_size_nb_sector))
00425 {
00426 case CTRL_GOOD:
00427 Usb_reset_endpoint_fifo_access(g_scsi_ep_ms_in);
00428
00429
00430 Usb_write_endpoint_data(g_scsi_ep_ms_in, 32,
00431 sbc_format_mcu_to_scsi_data(32, mem_size_nb_sector));
00432
00433
00434 Usb_write_endpoint_data(g_scsi_ep_ms_in, 32,
00435 Sbc_format_mcu_to_scsi_data(32, 512));
00436
00437 Sbc_valid_write_usb(SBC_READ_CAPACITY_LENGTH);
00438 sbc_lun_status_is_good();
00439 return TRUE;
00440
00441 case CTRL_NO_PRESENT:
00442 sbc_lun_status_is_not_present();
00443 break;
00444
00445 case CTRL_BUSY:
00446 sbc_lun_status_is_busy_or_change();
00447 break;
00448
00449 case CTRL_FAIL:
00450 default:
00451 sbc_lun_status_is_fail();
00452 break;
00453 }
00454 return FALSE;
00455 }
00456
00457
00458 Bool sbc_read_10(void)
00459 {
00460 U32 mass_addr;
00461 U16 mass_size;
00462
00463
00464 MSB0W(mass_addr) = g_scsi_command[2];
00465 MSB1W(mass_addr) = g_scsi_command[3];
00466 MSB2W(mass_addr) = g_scsi_command[4];
00467 MSB3W(mass_addr) = g_scsi_command[5];
00468
00469
00470 MSB(mass_size) = g_scsi_command[7];
00471 LSB(mass_size) = g_scsi_command[8];
00472
00473 if( ms_endpoint == EP_MS_OUT )
00474 {
00475
00476 sbc_lun_status_is_cdb_field();
00477 return FALSE;
00478 }
00479
00480
00481 if( 0 == g_scsi_data_remaining )
00482 {
00483 if( mass_size == (g_scsi_data_remaining/512) )
00484 {
00485 sbc_lun_status_is_good();
00486 }else{
00487 sbc_lun_status_is_cdb_field();
00488 }
00489 return TRUE;
00490 }
00491
00492 switch (memory_2_usb(usb_LUN, mass_addr, g_scsi_data_remaining/512))
00493 {
00494 case CTRL_GOOD:
00495 if( mass_size == (g_scsi_data_remaining/512) )
00496 {
00497 sbc_lun_status_is_good();
00498 }else{
00499 sbc_lun_status_is_cdb_field();
00500 }
00501 g_scsi_data_remaining = 0;
00502 return TRUE;
00503
00504 case CTRL_NO_PRESENT:
00505 sbc_lun_status_is_not_present();
00506 break;
00507
00508 case CTRL_BUSY:
00509 sbc_lun_status_is_busy_or_change();
00510 break;
00511
00512 case CTRL_FAIL:
00513 default:
00514 sbc_lun_status_is_fail();
00515 break;
00516 }
00517
00518 return FALSE;
00519 }
00520
00521
00522 Bool sbc_write_10(void)
00523 {
00524 U32 mass_addr;
00525 U16 mass_size;
00526
00527
00528 MSB0W(mass_addr) = g_scsi_command[2];
00529 MSB1W(mass_addr) = g_scsi_command[3];
00530 MSB2W(mass_addr) = g_scsi_command[4];
00531 MSB3W(mass_addr) = g_scsi_command[5];
00532
00533
00534 MSB(mass_size) = g_scsi_command[7];
00535 LSB(mass_size) = g_scsi_command[8];
00536
00537 if( ms_endpoint == EP_MS_IN )
00538 {
00539
00540 sbc_lun_status_is_cdb_field();
00541 return FALSE;
00542 }
00543
00544
00545 if( 0 == g_scsi_data_remaining )
00546 {
00547 if( mass_size == (g_scsi_data_remaining/512) )
00548 {
00549 sbc_lun_status_is_good();
00550 }else{
00551 sbc_lun_status_is_cdb_field();
00552 }
00553 return TRUE;
00554 }
00555
00556 if (mem_wr_protect(usb_LUN))
00557 {
00558 sbc_lun_status_is_protected();
00559 return FALSE;
00560 }
00561
00562 switch (usb_2_memory(usb_LUN, mass_addr, g_scsi_data_remaining/512 ))
00563 {
00564 case CTRL_GOOD:
00565 if( mass_size == (g_scsi_data_remaining/512) )
00566 {
00567 sbc_lun_status_is_good();
00568 }else{
00569 sbc_lun_status_is_cdb_field();
00570 }
00571 g_scsi_data_remaining = 0;
00572 return TRUE;
00573
00574 case CTRL_NO_PRESENT:
00575 sbc_lun_status_is_not_present();
00576 break;
00577
00578 case CTRL_BUSY:
00579 sbc_lun_status_is_busy_or_change();
00580 break;
00581
00582 case CTRL_FAIL:
00583 default:
00584 sbc_lun_status_is_fail();
00585 break;
00586 }
00587 return FALSE;
00588 }
00589
00590
00591 static void sbc_header_mode_sense(Bool b_sense_10, U8 u8_data_length)
00592 {
00593 Usb_reset_endpoint_fifo_access(g_scsi_ep_ms_in);
00594
00595
00596 if (b_sense_10)
00597 {
00598 Usb_write_endpoint_data(g_scsi_ep_ms_in, 8, 0);
00599 }
00600 Usb_write_endpoint_data(g_scsi_ep_ms_in, 8, u8_data_length);
00601
00602
00603 Usb_write_endpoint_data(g_scsi_ep_ms_in, 8, SBC_MEDIUM_TYPE);
00604
00605
00606 Usb_write_endpoint_data(g_scsi_ep_ms_in, 8,
00607 (mem_wr_protect(usb_LUN)) ? SBC_DEV_SPEC_PARAM_WR_PROTECT :
00608 SBC_DEV_SPEC_PARAM_WR_ENABLE);
00609
00610 if (b_sense_10)
00611 {
00612
00613 Usb_write_endpoint_data(g_scsi_ep_ms_in, 16, 0);
00614 }
00615
00616
00617 if (b_sense_10)
00618 {
00619 Usb_write_endpoint_data(g_scsi_ep_ms_in, 8, 0);
00620 }
00621 Usb_write_endpoint_data(g_scsi_ep_ms_in, 8, SBC_BLOCK_DESCRIPTOR_LENGTH);
00622 }
00623
00624
00625 static void send_read_write_error_recovery_page(U8 length)
00626 {
00627 Usb_write_endpoint_data(g_scsi_ep_ms_in, 8, SBC_PAGE_CODE_READ_WRITE_ERROR_RECOVERY);
00628
00629
00630 Usb_write_endpoint_data(g_scsi_ep_ms_in, 8, SBC_PAGE_LENGTH_READ_WRITE_ERROR_RECOVERY);
00631 Usb_write_endpoint_data(g_scsi_ep_ms_in, 8, 0x80);
00632 Usb_write_endpoint_data(g_scsi_ep_ms_in, 8, SBC_READ_RETRY_COUNT);
00633 Usb_write_endpoint_data(g_scsi_ep_ms_in, 8, 0x00);
00634 Usb_write_endpoint_data(g_scsi_ep_ms_in, 8, 0x00);
00635 Usb_write_endpoint_data(g_scsi_ep_ms_in, 8, 0x00);
00636
00637 Usb_write_endpoint_data(g_scsi_ep_ms_in, 8, 0x00);
00638
00639 if (length > 12)
00640 {
00641 Usb_write_endpoint_data(g_scsi_ep_ms_in, 8, SBC_WRITE_RETRY_COUNT);
00642 Usb_write_endpoint_data(g_scsi_ep_ms_in, 8, 0x00);
00643 Usb_write_endpoint_data(g_scsi_ep_ms_in, 16,
00644 Sbc_format_mcu_to_scsi_data(16, SBC_RECOVERY_TIME_LIMIT));
00645 }
00646 }
00647
00648
00649 static void send_informational_exceptions_page(void)
00650 {
00651
00652 Usb_write_endpoint_data(g_scsi_ep_ms_in, 8, SBC_PAGE_CODE_INFORMATIONAL_EXCEPTIONS);
00653
00654
00655 Usb_write_endpoint_data(g_scsi_ep_ms_in, 8, SBC_PAGE_LENGTH_INFORMATIONAL_EXCEPTIONS);
00656
00657 Usb_write_endpoint_data(g_scsi_ep_ms_in, 8, 0x00);
00658
00659 Usb_write_endpoint_data(g_scsi_ep_ms_in, 8, SBC_MRIE_GENERATE_NO_SENSE);
00660
00661 Usb_write_endpoint_data(g_scsi_ep_ms_in, 32,
00662 Sbc_format_mcu_to_scsi_data(32, 0x00000000));
00663
00664 Usb_write_endpoint_data(g_scsi_ep_ms_in, 32,
00665 Sbc_format_mcu_to_scsi_data(32, 0x00000001));
00666 }
00667
00668
00669 void sbc_lun_status_is_good(void)
00670 {
00671 Sbc_send_good();
00672 Sbc_build_sense(SBC_SENSE_KEY_NO_SENSE, SBC_ASC_NO_ADDITIONAL_SENSE_INFORMATION, 0x00);
00673 }
00674
00675
00676 void sbc_lun_status_is_not_present(void)
00677 {
00678 Sbc_send_failed();
00679 Sbc_build_sense(SBC_SENSE_KEY_NOT_READY, SBC_ASC_MEDIUM_NOT_PRESENT, 0x00);
00680 }
00681
00682
00683 void sbc_lun_status_is_busy_or_change(void)
00684 {
00685 Sbc_send_failed();
00686 Sbc_build_sense(SBC_SENSE_KEY_UNIT_ATTENTION, SBC_ASC_NOT_READY_TO_READY_CHANGE, 0x00);
00687 }
00688
00689
00690 void sbc_lun_status_is_fail(void)
00691 {
00692 Sbc_send_failed();
00693 Sbc_build_sense(SBC_SENSE_KEY_HARDWARE_ERROR, SBC_ASC_NO_ADDITIONAL_SENSE_INFORMATION, 0x00);
00694 }
00695
00696
00697 void sbc_lun_status_is_protected(void)
00698 {
00699 Sbc_send_failed();
00700 Sbc_build_sense(SBC_SENSE_KEY_DATA_PROTECT, SBC_ASC_WRITE_PROTECTED, 0x00);
00701 }
00702
00703
00704 void sbc_lun_status_is_cdb_field(void)
00705 {
00706 Sbc_send_failed();
00707 Sbc_build_sense(SBC_SENSE_KEY_ILLEGAL_REQUEST, SBC_ASC_INVALID_FIELD_IN_CDB, 0x00);
00708 }
00709
00710
00711 #endif // USB_DEVICE_FEATURE == ENABLED