00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include "SBCMethods.h"
00040 #include "MSDDStateMachine.h"
00041 #include "USBD.h"
00042
00043 #include "MSDIOFifo.h"
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053 #ifdef MSDIO_READ10_CHUNK_SIZE
00054
00055 #define SBC_READ_CHUNK(pLun, lba, pFifo, pCb, pArg) \
00056 LUN_Read((pLun), (lba), \
00057 &(pFifo)->pBuffer[(pFifo)->inputNdx], \
00058 ((pFifo)->chunkSize/(pFifo)->blockSize), \
00059 (TransferCallback)(pCb), (void*)pArg)
00060
00061 #define SBC_TX_CHUNK(ep, pFifo, pCb, pArg) \
00062 USBD_Write( (ep), \
00063 &(pFifo)->pBuffer[(pFifo)->outputNdx], \
00064 (pFifo)->chunkSize, \
00065 (TransferCallback)(pCb), (void*)(pArg))
00066 #endif
00067
00068 #ifdef MSDIO_WRITE10_CHUNK_SIZE
00069
00070 #define SBC_RX_CHUNK(ep, pFifo,pCb,pArg) \
00071 USBD_Read( (ep), \
00072 &(pFifo)->pBuffer[(pFifo)->inputNdx], \
00073 (pFifo)->chunkSize, \
00074 (TransferCallback)(pCb), (void*)(pArg))
00075
00076 #define SBC_WRITE_CHUNK(pLun, lba, pFifo, pCb, pArg) \
00077 LUN_Write((pLun), (lba), \
00078 &(pFifo)->pBuffer[(pFifo)->outputNdx], \
00079 ((pFifo)->chunkSize/(pFifo)->blockSize), \
00080 (TransferCallback)(pCb), (void*)(pArg))
00081 #endif
00082
00083
00084
00085
00086
00087
00088 static const SBCModeParameterHeader6 modeParameterHeader6 = {
00089
00090 sizeof(SBCModeParameterHeader6) - 1,
00091
00092 SBC_MEDIUM_TYPE_DIRECT_ACCESS_BLOCK_DEVICE,
00093
00094 0,
00095
00096 0,
00097
00098 0,
00099
00100 0,
00101
00102 0
00103
00104 };
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117 static void MSDDriver_Callback(MSDTransfer *transfer,
00118 uint8_t status,
00119 uint32_t transferred,
00120 uint32_t remaining)
00121 {
00122 TRACE_DEBUG_WP( "Cbk " ) ;
00123 transfer->semaphore++;
00124 transfer->status = status;
00125 transfer->transferred = transferred;
00126 transfer->remaining = remaining;
00127 }
00128
00129
00130
00131
00132
00133
00134
00135 static unsigned char SBCLunIsReady(MSDLun *lun)
00136 {
00137 unsigned char lunIsReady = 0;
00138
00139 if (lun->media == 0 || lun->status < LUN_CHANGED) {
00140 TRACE_INFO("SBCLunIsReady: Not Present!\n\r");
00141 SBC_UpdateSenseData(&(lun->requestSenseData),
00142 SBC_SENSE_KEY_NOT_READY,
00143 SBC_ASC_MEDIUM_NOT_PRESENT,
00144 0);
00145
00146 }
00147 else if (lun->status < LUN_READY) {
00148 TRACE_INFO("SBCLunIsReady: Changing!\n\r");
00149 SBC_UpdateSenseData(&(lun->requestSenseData),
00150 SBC_SENSE_KEY_UNIT_ATTENTION,
00151 SBC_ASC_NOT_READY_TO_READY_CHANGE,
00152 0);
00153 lun->status = LUN_READY;
00154 }
00155 else {
00156
00157 lunIsReady = 1;
00158 }
00159
00160 return lunIsReady;
00161 }
00162
00163
00164
00165
00166
00167
00168
00169 static unsigned char SBCLunCanBeWritten(MSDLun *lun)
00170 {
00171 unsigned char canBeWritten = 0;
00172
00173 if (!SBCLunIsReady(lun)) {
00174
00175 TRACE_WARNING("SBCLunCanBeWritten: Not Ready!\n\r");
00176 }
00177 else if (lun->protected) {
00178
00179 TRACE_WARNING("SBCLunCanBeWritten: Protected!\n\r");
00180 SBC_UpdateSenseData(&(lun->requestSenseData),
00181 SBC_SENSE_KEY_DATA_PROTECT,
00182 SBC_ASC_WRITE_PROTECTED,
00183 0);
00184 }
00185 else {
00186
00187 canBeWritten = 1;
00188 }
00189
00190 return canBeWritten;
00191 }
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207 static unsigned char SBC_Write10(MSDLun *lun,
00208 MSDCommandState *commandState)
00209 {
00210 unsigned char status;
00211 unsigned char result = MSDD_STATUS_INCOMPLETE;
00212 SBCRead10 *command = (SBCRead10 *) commandState->cbw.pCommand;
00213 MSDTransfer *transfer = &(commandState->transfer);
00214 MSDTransfer *disktransfer = &(commandState->disktransfer);
00215 MSDIOFifo *fifo = &lun->ioFifo;
00216 unsigned int oldChunkSize, newChunkSize;
00217
00218 if (commandState->state == 0) {
00219
00220 commandState->state = SBC_STATE_WRITE;
00221
00222
00223 if (!SBCLunCanBeWritten(lun)) {
00224
00225 return MSDD_STATUS_RW;
00226 }
00227 else {
00228
00229
00230
00231 fifo->dataTotal = commandState->length;
00232 fifo->blockSize = lun->blockSize * MED_GetBlockSize(lun->media);
00233 #ifdef MSDIO_WRITE10_CHUNK_SIZE
00234 if ( fifo->dataTotal >= 64 * 1024
00235 && fifo->blockSize < MSDIO_WRITE10_CHUNK_SIZE)
00236 fifo->chunkSize = MSDIO_WRITE10_CHUNK_SIZE;
00237 else
00238 fifo->chunkSize = fifo->blockSize;
00239 #endif
00240 fifo->fullCnt = 0;
00241 fifo->nullCnt = 0;
00242
00243
00244 fifo->outputNdx = 0;
00245 fifo->outputTotal = 0;
00246 fifo->outputState = MSDIO_IDLE;
00247 transfer->semaphore = 0;
00248
00249
00250 fifo->inputNdx = 0;
00251 fifo->inputTotal = 0;
00252 fifo->inputState = MSDIO_START;
00253 disktransfer->semaphore = 0;
00254 }
00255
00256 }
00257
00258 if (commandState->length == 0) {
00259
00260
00261 if (lun->dataMonitor) {
00262
00263 lun->dataMonitor(0, fifo->dataTotal, fifo->nullCnt, fifo->fullCnt);
00264 }
00265 return MSDD_STATUS_SUCCESS;
00266 }
00267 oldChunkSize = fifo->chunkSize;
00268 if ((fifo->dataTotal - fifo->inputTotal) < fifo->chunkSize) {
00269 newChunkSize = fifo->dataTotal - fifo->inputTotal;
00270 fifo->chunkSize = newChunkSize;
00271 }
00272
00273 switch(fifo->inputState) {
00274
00275
00276 case MSDIO_IDLE:
00277
00278
00279 if (fifo->inputTotal < fifo->dataTotal &&
00280 fifo->inputTotal - fifo->outputTotal < fifo->bufferSize) {
00281
00282 fifo->inputState = MSDIO_START;
00283 }
00284 break;
00285
00286
00287 case MSDIO_START:
00288
00289
00290
00291 if (fifo->outputState == MSDIO_ERROR) {
00292
00293 TRACE_INFO_WP("udErr ");
00294 fifo->inputState = MSDIO_ERROR;
00295 break;
00296 }
00297
00298
00299 if (MED_IsMappedWRSupported(lun->media)) {
00300
00301
00302 #if 1
00303 uint32_t mappedAddr = MED_GetMappedAddress(
00304 lun->media,
00305 DWORDB(command->pLogicalBlockAddress)
00306 * lun->blockSize);
00307
00308 status = USBD_Read(commandState->pipeOUT,
00309 (void*)(mappedAddr),
00310
00311
00312
00313
00314
00315
00316
00317
00318 fifo->dataTotal,
00319 (TransferCallback) MSDDriver_Callback,
00320 (void *) transfer);
00321 #else
00322 status = MSDD_Read((void*)
00323 ((lun->media->baseAddress
00324 + (lun->baseAddress
00325 + DWORDB(command->pLogicalBlockAddress)
00326 * lun->blockSize
00327 )
00328 ) * MED_GetBlockSize(lun->media)
00329 ),
00330 fifo->dataTotal,
00331 (TransferCallback) MSDDriver_Callback,
00332 (void *) transfer);
00333 #endif
00334 }
00335 else {
00336 #ifdef MSDIO_WRITE10_CHUNK_SIZE
00337 status = SBC_RX_CHUNK(commandState->pipeOUT,
00338 fifo, MSDDriver_Callback, transfer);
00339 #else
00340
00341 #if 1
00342 status = USBD_Read(commandState->pipeOUT,
00343 (void*)&fifo->pBuffer[fifo->inputNdx],
00344 fifo->blockSize,
00345 (TransferCallback) MSDDriver_Callback,
00346 (void *) transfer);
00347 #else
00348 status = MSDD_Read((void*)&fifo->pBuffer[fifo->inputNdx],
00349 fifo->blockSize,
00350 (TransferCallback) MSDDriver_Callback,
00351 (void *) transfer);
00352 #endif
00353 #endif
00354 }
00355
00356
00357
00358 if (status != USBD_STATUS_SUCCESS) {
00359
00360 TRACE_WARNING(
00361 "RBC_Write10: Failed to start receiving\n\r");
00362 SBC_UpdateSenseData(&(lun->requestSenseData),
00363 SBC_SENSE_KEY_HARDWARE_ERROR,
00364 0,
00365 0);
00366 result = MSDD_STATUS_ERROR;
00367 }
00368 else {
00369
00370 TRACE_INFO_WP("uRx ");
00371
00372
00373
00374 fifo->inputState = MSDIO_WAIT;
00375 }
00376 break;
00377
00378
00379
00380
00381 case MSDIO_WAIT:
00382
00383
00384 TRACE_INFO_WP("uWait ");
00385
00386
00387
00388 if (transfer->semaphore > 0) {
00389
00390 transfer->semaphore--;
00391 fifo->inputState = MSDIO_NEXT;
00392 }
00393 break;
00394
00395
00396
00397 case MSDIO_NEXT:
00398
00399
00400
00401
00402 if (transfer->status != USBD_STATUS_SUCCESS) {
00403
00404 TRACE_WARNING(
00405 "RBC_Write10: Failed to received\n\r");
00406 SBC_UpdateSenseData(&(lun->requestSenseData),
00407 SBC_SENSE_KEY_HARDWARE_ERROR,
00408 0,
00409 0);
00410 result = MSDD_STATUS_ERROR;
00411 }
00412 else {
00413
00414 TRACE_INFO_WP("uNxt ");
00415
00416
00417
00418 if (MED_IsMappedWRSupported(lun->media)) {
00419
00420 fifo->inputTotal = fifo->dataTotal;
00421 fifo->inputState = MSDIO_IDLE;
00422 }
00423 else {
00424
00425
00426 #ifdef MSDIO_WRITE10_CHUNK_SIZE
00427
00428 MSDIOFifo_IncNdx(fifo->inputNdx,
00429 fifo->chunkSize,
00430 fifo->bufferSize);
00431 fifo->inputTotal += fifo->chunkSize;
00432
00433 #else
00434 MSDIOFifo_IncNdx(fifo->inputNdx,
00435 fifo->blockSize,
00436 fifo->bufferSize);
00437 fifo->inputTotal += fifo->blockSize;
00438 #endif
00439
00440
00441
00442
00443
00444 if (fifo->inputTotal >= fifo->dataTotal) {
00445
00446 fifo->inputState = MSDIO_IDLE;
00447 }
00448
00449
00450 else if (fifo->inputNdx == fifo->outputNdx) {
00451 fifo->inputState = MSDIO_IDLE;
00452 fifo->fullCnt ++;
00453
00454 TRACE_DEBUG_WP("ufFull%d ", fifo->inputNdx);
00455 }
00456
00457
00458 else if (fifo->inputTotal < fifo->dataTotal) {
00459 fifo->inputState = MSDIO_START;
00460
00461 TRACE_INFO_WP("uStart ");
00462 }
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473 }
00474
00475 }
00476 break;
00477
00478
00479
00480
00481 case MSDIO_ERROR:
00482
00483
00484
00485 TRACE_WARNING_WP("uErr ");
00486 commandState->length -= fifo->inputTotal;
00487 return MSDD_STATUS_RW;
00488
00489 }
00490
00491 fifo->chunkSize = oldChunkSize ;
00492 if ((fifo->dataTotal - fifo->outputTotal) < fifo->chunkSize) {
00493 newChunkSize = fifo->dataTotal - fifo->outputTotal;
00494 fifo->chunkSize = newChunkSize;
00495 }
00496 switch(fifo->outputState) {
00497
00498
00499
00500 case MSDIO_IDLE:
00501
00502
00503 if (fifo->outputTotal < fifo->inputTotal) {
00504
00505 fifo->outputState = MSDIO_START;
00506 }
00507 break;
00508
00509
00510
00511 case MSDIO_START:
00512
00513
00514
00515
00516
00517 if (MED_IsMappedWRSupported(lun->media)) {
00518
00519 MSDDriver_Callback(disktransfer, MED_STATUS_SUCCESS, 0, 0);
00520 status = LUN_STATUS_SUCCESS;
00521 }
00522 else {
00523 #ifdef MSDIO_WRITE10_CHUNK_SIZE
00524 status = SBC_WRITE_CHUNK(lun, DWORDB(command->pLogicalBlockAddress),
00525 fifo, MSDDriver_Callback, disktransfer);
00526 #else
00527 status = LUN_Write(lun,
00528 DWORDB(command->pLogicalBlockAddress),
00529 &fifo->pBuffer[fifo->outputNdx],
00530 1,
00531 (TransferCallback) MSDDriver_Callback,
00532 (void *) disktransfer);
00533 #endif
00534 }
00535
00536
00537
00538 if (status != USBD_STATUS_SUCCESS) {
00539
00540 TRACE_WARNING(
00541 "RBC_Write10: Failed to start write - ");
00542
00543 if (!SBCLunCanBeWritten(lun)) {
00544
00545 TRACE_WARNING("?\n\r");
00546 SBC_UpdateSenseData(&(lun->requestSenseData),
00547 SBC_SENSE_KEY_NOT_READY,
00548 0,
00549 0);
00550 }
00551
00552 fifo->outputState = MSDIO_ERROR;
00553 }
00554 else {
00555
00556
00557
00558 fifo->outputState = MSDIO_WAIT;
00559 }
00560 break;
00561
00562
00563
00564
00565 case MSDIO_WAIT:
00566
00567
00568 TRACE_INFO_WP("dWait ");
00569
00570
00571
00572 if (disktransfer->semaphore > 0) {
00573
00574
00575
00576 disktransfer->semaphore--;
00577 fifo->outputState = MSDIO_NEXT;
00578 }
00579 break;
00580
00581
00582
00583 case MSDIO_NEXT:
00584
00585
00586
00587
00588 if (transfer->status != USBD_STATUS_SUCCESS) {
00589
00590 TRACE_WARNING(
00591 "RBC_Write10: Failed to write\n\r");
00592 SBC_UpdateSenseData(&(lun->requestSenseData),
00593 SBC_SENSE_KEY_RECOVERED_ERROR,
00594 SBC_ASC_TOO_MUCH_WRITE_DATA,
00595 0);
00596 result = MSDD_STATUS_ERROR;
00597 }
00598 else {
00599
00600 TRACE_INFO_WP("dNxt ");
00601
00602
00603
00604
00605
00606
00607 if (MED_IsMappedWRSupported(lun->media)) {
00608
00609 commandState->length = 0;
00610 fifo->outputState = MSDIO_IDLE;
00611 }
00612 else {
00613
00614
00615
00616 #ifdef MSDIO_WRITE10_CHUNK_SIZE
00617 STORE_DWORDB(DWORDB(command->pLogicalBlockAddress)
00618 + fifo->chunkSize/fifo->blockSize,
00619 command->pLogicalBlockAddress);
00620 MSDIOFifo_IncNdx(fifo->outputNdx,
00621 fifo->chunkSize,
00622 fifo->bufferSize);
00623 fifo->outputTotal += fifo->chunkSize;
00624 #else
00625 STORE_DWORDB(DWORDB(command->pLogicalBlockAddress) + 1,
00626 command->pLogicalBlockAddress);
00627 MSDIOFifo_IncNdx(fifo->outputNdx,
00628 fifo->blockSize,
00629 fifo->bufferSize);
00630 fifo->outputTotal += fifo->blockSize;
00631 #endif
00632
00633
00634
00635
00636
00637 if (fifo->outputTotal >= fifo->dataTotal) {
00638
00639 fifo->outputState = MSDIO_IDLE;
00640 commandState->length = 0;
00641 TRACE_INFO_WP("dDone ");
00642 }
00643
00644
00645 else if (fifo->outputTotal < fifo->inputTotal) {
00646
00647 fifo->outputState = MSDIO_START;
00648 TRACE_INFO_WP("dStart ");
00649 }
00650
00651
00652 else {
00653 fifo->outputState = MSDIO_IDLE;
00654 fifo->nullCnt ++;
00655
00656 TRACE_DEBUG_WP("dfNull%d ", fifo->outputNdx);
00657 }
00658 }
00659 }
00660 break;
00661
00662
00663
00664
00665 case MSDIO_ERROR:
00666
00667
00668 break;
00669 }
00670
00671 return result;
00672 }
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687 static unsigned char SBC_Read10(MSDLun *lun,
00688 MSDCommandState *commandState)
00689 {
00690 unsigned char status;
00691 unsigned char result = MSDD_STATUS_INCOMPLETE;
00692 SBCRead10 *command = (SBCRead10 *) commandState->cbw.pCommand;
00693 MSDTransfer *transfer = &(commandState->transfer);
00694 MSDTransfer *disktransfer = &(commandState->disktransfer);
00695 MSDIOFifo *fifo = &lun->ioFifo;
00696 unsigned int oldChunkSize, newChunkSize;
00697
00698
00699 if (commandState->state == 0) {
00700
00701 commandState->state = SBC_STATE_READ;
00702
00703 if (!SBCLunIsReady(lun)) {
00704
00705 return MSDD_STATUS_RW;
00706 }
00707 else {
00708
00709
00710
00711 fifo->dataTotal = commandState->length;
00712 fifo->blockSize = lun->blockSize * MED_GetBlockSize(lun->media);
00713 #ifdef MSDIO_READ10_CHUNK_SIZE
00714 if ( fifo->dataTotal >= 64 * 1024
00715 && fifo->blockSize < MSDIO_READ10_CHUNK_SIZE){
00716 fifo->chunkSize = MSDIO_READ10_CHUNK_SIZE;
00717
00718 }
00719 else
00720 fifo->chunkSize = fifo->blockSize;
00721 #endif
00722 fifo->fullCnt = 0;
00723 fifo->nullCnt = 0;
00724
00725 #ifdef MSDIO_FIFO_OFFSET
00726
00727
00728 if (fifo->dataTotal / fifo->bufferSize >= 2)
00729 fifo->bufferOffset = MSDIO_FIFO_OFFSET;
00730 else
00731 fifo->bufferOffset = 0;
00732 #endif
00733
00734
00735
00736 fifo->outputNdx = 0;
00737 fifo->outputTotal = 0;
00738 fifo->outputState = MSDIO_IDLE;
00739 transfer->semaphore = 0;
00740
00741
00742
00743 fifo->inputNdx = 0;
00744 fifo->inputTotal = 0;
00745 fifo->inputState = MSDIO_START;
00746 disktransfer->semaphore = 0;
00747 }
00748 }
00749
00750
00751
00752 if (commandState->length == 0) {
00753
00754
00755
00756 if (lun->dataMonitor) {
00757
00758 lun->dataMonitor(1, fifo->dataTotal, fifo->nullCnt, fifo->fullCnt);
00759 }
00760 return MSDD_STATUS_SUCCESS;
00761 }
00762
00763
00764 oldChunkSize = fifo->chunkSize;
00765 if ((fifo->dataTotal - fifo->inputTotal) < fifo->chunkSize) {
00766 newChunkSize = fifo->dataTotal - fifo->inputTotal;
00767 fifo->chunkSize = newChunkSize;
00768 }
00769 switch(fifo->inputState) {
00770
00771
00772
00773 case MSDIO_IDLE:
00774
00775
00776 if (fifo->inputTotal < fifo->dataTotal &&
00777 fifo->inputTotal - fifo->outputTotal < fifo->bufferSize) {
00778
00779 fifo->inputState = MSDIO_START;
00780 }
00781 break;
00782
00783
00784
00785 case MSDIO_START:
00786
00787
00788
00789 if (MED_IsMappedRDSupported(lun->media)) {
00790
00791
00792
00793 MSDDriver_Callback(disktransfer, MED_STATUS_SUCCESS, 0, 0);
00794 status = LUN_STATUS_SUCCESS;
00795 }
00796 else {
00797 #ifdef MSDIO_READ10_CHUNK_SIZE
00798 status = SBC_READ_CHUNK(lun, DWORDB(command->pLogicalBlockAddress),
00799 fifo, MSDDriver_Callback, disktransfer);
00800 #else
00801
00802 status = LUN_Read(lun,
00803 DWORDB(command->pLogicalBlockAddress),
00804 &fifo->pBuffer[fifo->inputNdx],
00805 1,
00806 (TransferCallback) MSDDriver_Callback,
00807 (void *)disktransfer);
00808 #endif
00809 }
00810
00811
00812
00813 if (status != LUN_STATUS_SUCCESS) {
00814
00815 TRACE_WARNING("RBC_Read10: Failed to start reading\n\r");
00816 if (SBCLunIsReady(lun)) {
00817
00818 SBC_UpdateSenseData(&(lun->requestSenseData),
00819 SBC_SENSE_KEY_NOT_READY,
00820 SBC_ASC_LOGICAL_UNIT_NOT_READY,
00821 0);
00822 }
00823
00824 fifo->inputState = MSDIO_ERROR;
00825 }
00826 else {
00827
00828 TRACE_INFO_WP("dRd ");
00829
00830
00831
00832 fifo->inputState = MSDIO_WAIT;
00833 }
00834 break;
00835
00836
00837
00838
00839 case MSDIO_WAIT:
00840
00841
00842
00843
00844 if (disktransfer->semaphore > 0) {
00845
00846 TRACE_INFO_WP("dOk ");
00847
00848
00849
00850 disktransfer->semaphore--;
00851 fifo->inputState = MSDIO_NEXT;
00852 }
00853 break;
00854
00855
00856
00857 case MSDIO_NEXT:
00858
00859
00860
00861
00862 if (disktransfer->status != USBD_STATUS_SUCCESS) {
00863
00864 TRACE_WARNING(
00865 "RBC_Read10: Failed to read media\n\r");
00866 SBC_UpdateSenseData(&(lun->requestSenseData),
00867 SBC_SENSE_KEY_RECOVERED_ERROR,
00868 SBC_ASC_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE,
00869 0);
00870 result = MSDD_STATUS_ERROR;
00871 }
00872 else {
00873
00874 TRACE_INFO_WP("dNxt ");
00875
00876 if (MED_IsMappedRDSupported(lun->media)) {
00877
00878
00879
00880 fifo->inputState = MSDIO_IDLE;
00881 fifo->inputTotal = fifo->dataTotal;
00882 }
00883 else {
00884
00885
00886
00887 #ifdef MSDIO_READ10_CHUNK_SIZE
00888
00889
00890 STORE_DWORDB(DWORDB(command->pLogicalBlockAddress)
00891 + fifo->chunkSize/fifo->blockSize,
00892 command->pLogicalBlockAddress);
00893 MSDIOFifo_IncNdx(fifo->inputNdx,
00894 fifo->chunkSize,
00895 fifo->bufferSize);
00896 fifo->inputTotal += fifo->chunkSize;
00897 #else
00898
00899
00900 STORE_DWORDB(DWORDB(command->pLogicalBlockAddress) + 1,
00901 command->pLogicalBlockAddress);
00902
00903
00904
00905 MSDIOFifo_IncNdx(fifo->inputNdx,
00906 fifo->blockSize,
00907 fifo->bufferSize);
00908 fifo->inputTotal += fifo->blockSize;
00909 #endif
00910
00911
00912
00913
00914
00915 if (fifo->inputTotal >= fifo->dataTotal) {
00916
00917 TRACE_INFO_WP("dDone ");
00918 fifo->inputState = MSDIO_IDLE;
00919 }
00920
00921
00922 else if (fifo->inputNdx == fifo->outputNdx) {
00923
00924 TRACE_INFO_WP("dfFull%d ", (int)fifo->inputNdx);
00925 fifo->inputState = MSDIO_IDLE;
00926 fifo->fullCnt ++;
00927 }
00928
00929
00930 else if (fifo->inputTotal < fifo->dataTotal) {
00931
00932 TRACE_DEBUG_WP("dStart ");
00933 fifo->inputState = MSDIO_START;
00934 }
00935 }
00936
00937 }
00938
00939 break;
00940
00941
00942
00943 case MSDIO_ERROR:
00944
00945 break;
00946 }
00947 fifo->chunkSize = oldChunkSize ;
00948
00949 if ((fifo->dataTotal - fifo->outputTotal) < fifo->chunkSize) {
00950 newChunkSize = fifo->dataTotal - fifo->outputTotal;
00951 fifo->chunkSize = newChunkSize;
00952 }
00953
00954 switch(fifo->outputState) {
00955
00956
00957
00958 case MSDIO_IDLE:
00959
00960
00961 if (fifo->outputTotal < fifo->inputTotal) {
00962
00963 #ifdef MSDIO_FIFO_OFFSET
00964
00965
00966 if (fifo->bufferOffset) {
00967 if (fifo->inputTotal < fifo->bufferOffset) {
00968 break;
00969 }
00970 fifo->bufferOffset = 0;
00971 }
00972 #endif
00973 fifo->outputState = MSDIO_START;
00974 }
00975 break;
00976
00977
00978
00979 case MSDIO_START:
00980
00981
00982
00983 if (fifo->outputState == MSDIO_ERROR) {
00984
00985 fifo->inputState = MSDIO_ERROR;
00986 break;
00987 }
00988
00989
00990 if (MED_IsMappedRDSupported(lun->media)) {
00991 #if 1
00992 uint32_t mappedAddr = MED_GetMappedAddress(
00993 lun->media,
00994 DWORDB(command->pLogicalBlockAddress)
00995 * lun->blockSize);
00996
00997 status = USBD_Write(commandState->pipeIN,
00998 (void*)(mappedAddr),
00999
01000
01001
01002
01003
01004
01005
01006
01007 commandState->length,
01008 (TransferCallback) MSDDriver_Callback,
01009 (void *) transfer);
01010 #else
01011 status = MSDD_Write((void*)
01012 ((lun->media->baseAddress
01013 + (lun->baseAddress
01014 + DWORDB(command->pLogicalBlockAddress)
01015 * lun->blockSize
01016 )
01017 ) * MED_GetBlockSize(lun->media)
01018 ),
01019 commandState->length,
01020 (TransferCallback) MSDDriver_Callback,
01021 (void *) transfer);
01022 #endif
01023 }
01024 else {
01025 #ifdef MSDIO_READ10_CHUNK_SIZE
01026 status = SBC_TX_CHUNK(commandState->pipeIN,
01027 fifo, MSDDriver_Callback, transfer);
01028 #else
01029 #if 1
01030 status = USBD_Write(commandState->pipeIN,
01031 &fifo->pBuffer[fifo->outputNdx],
01032 fifo->blockSize,
01033 (TransferCallback) MSDDriver_Callback,
01034 (void *) transfer);
01035 #else
01036 status = MSDD_Write(&fifo->pBuffer[fifo->outputNdx],
01037 fifo->blockSize,
01038 (TransferCallback) MSDDriver_Callback,
01039 (void *) transfer);
01040 #endif
01041 #endif
01042 }
01043
01044
01045 if (status != USBD_STATUS_SUCCESS) {
01046
01047 TRACE_WARNING(
01048 "RBC_Read10: Failed to start to send\n\r");
01049 SBC_UpdateSenseData(&(lun->requestSenseData),
01050 SBC_SENSE_KEY_HARDWARE_ERROR,
01051 0,
01052 0);
01053 result = MSDD_STATUS_ERROR;
01054 }
01055 else {
01056
01057 TRACE_INFO_WP("uTx ");
01058
01059
01060
01061 fifo->outputState = MSDIO_WAIT;
01062 }
01063 break;
01064
01065
01066
01067
01068 case MSDIO_WAIT:
01069
01070
01071
01072
01073 if (transfer->semaphore > 0) {
01074
01075 TRACE_INFO_WP("uOk ");
01076
01077
01078
01079 transfer->semaphore--;
01080 fifo->outputState = MSDIO_NEXT;
01081 }
01082 break;
01083
01084
01085
01086 case MSDIO_NEXT:
01087
01088
01089
01090
01091 if (transfer->status != USBD_STATUS_SUCCESS) {
01092
01093 TRACE_WARNING(
01094 "RBC_Read10: Failed to send data\n\r");
01095 SBC_UpdateSenseData(&(lun->requestSenseData),
01096 SBC_SENSE_KEY_HARDWARE_ERROR,
01097 0,
01098 0);
01099 result = MSDD_STATUS_ERROR;
01100 }
01101 else {
01102
01103 TRACE_INFO_WP("uNxt ");
01104
01105 if (MED_IsMappedRDSupported(lun->media)) {
01106
01107 commandState->length = 0;
01108 }
01109 else {
01110
01111
01112
01113 #ifdef MSDIO_READ10_CHUNK_SIZE
01114 MSDIOFifo_IncNdx(fifo->outputNdx,
01115 fifo->chunkSize,
01116 fifo->bufferSize);
01117 fifo->outputTotal += fifo->chunkSize;
01118 #else
01119 MSDIOFifo_IncNdx(fifo->outputNdx,
01120 fifo->blockSize,
01121 fifo->bufferSize);
01122 fifo->outputTotal += fifo->blockSize;
01123 #endif
01124
01125
01126
01127
01128
01129 if (fifo->outputTotal >= fifo->dataTotal) {
01130
01131 fifo->outputState = MSDIO_IDLE;
01132 commandState->length = 0;
01133 TRACE_INFO_WP("uDone ");
01134 }
01135
01136
01137 else if (fifo->inputNdx == fifo->outputNdx) {
01138
01139 TRACE_INFO_WP("ufNull%d ", (int)fifo->outputNdx);
01140 fifo->outputState = MSDIO_IDLE;
01141 fifo->nullCnt ++;
01142 }
01143
01144
01145 else if (fifo->outputTotal < fifo->inputTotal) {
01146
01147 TRACE_DEBUG_WP("uStart ");
01148 fifo->outputState = MSDIO_START;
01149 }
01150 }
01151
01152 }
01153 break;
01154
01155
01156
01157 case MSDIO_ERROR:
01158
01159 break;
01160 }
01161
01162 return result;
01163 }
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177 static unsigned char SBC_ReadCapacity10(MSDLun *lun,
01178 MSDCommandState *commandState)
01179 {
01180 unsigned char result = MSDD_STATUS_INCOMPLETE;
01181 unsigned char status;
01182 MSDTransfer *transfer = &(commandState->transfer);
01183
01184 if (!SBCLunIsReady(lun)) {
01185
01186 TRACE_INFO("SBC_ReadCapacity10: Not Ready!\n\r");
01187 return MSDD_STATUS_RW;
01188 }
01189
01190
01191 if (commandState->state == 0) {
01192
01193 commandState->state = SBC_STATE_WRITE;
01194 }
01195
01196
01197 switch (commandState->state) {
01198
01199 case SBC_STATE_WRITE:
01200
01201
01202
01203 #if 1
01204 status = USBD_Write(commandState->pipeIN,
01205 &(lun->readCapacityData),
01206 commandState->length,
01207 (TransferCallback) MSDDriver_Callback,
01208 (void *) transfer);
01209 #else
01210 status = MSDD_Write(&(lun->readCapacityData),
01211 commandState->length,
01212 (TransferCallback) MSDDriver_Callback,
01213 (void *) transfer);
01214 #endif
01215
01216
01217 if (status != USBD_STATUS_SUCCESS) {
01218
01219 TRACE_WARNING(
01220 "RBC_ReadCapacity: Cannot start sending data\n\r");
01221 result = MSDD_STATUS_ERROR;
01222 }
01223 else {
01224
01225
01226 TRACE_INFO_WP("Sending ");
01227 commandState->state = SBC_STATE_WAIT_WRITE;
01228 }
01229 break;
01230
01231
01232 case SBC_STATE_WAIT_WRITE:
01233
01234
01235
01236 if (transfer->semaphore > 0) {
01237
01238
01239 transfer->semaphore--;
01240
01241 if (transfer->status != USBD_STATUS_SUCCESS) {
01242
01243 TRACE_WARNING("RBC_ReadCapacity: Cannot send data\n\r");
01244 result = MSDD_STATUS_ERROR;
01245 }
01246 else {
01247
01248 TRACE_INFO_WP("Sent ");
01249 result = MSDD_STATUS_SUCCESS;
01250 }
01251 commandState->length -= transfer->transferred;
01252 }
01253 break;
01254 }
01255
01256 return result;
01257 }
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271 static unsigned char SBC_Inquiry(MSDLun *lun,
01272 MSDCommandState *commandState)
01273 {
01274 unsigned char result = MSDD_STATUS_INCOMPLETE;
01275 unsigned char status;
01276 MSDTransfer *transfer = &(commandState->transfer);
01277
01278
01279 if (commandState->length == 0) {
01280
01281
01282 result = MSDD_STATUS_SUCCESS;
01283 }
01284
01285 else if (commandState->state == 0) {
01286
01287 commandState->state = SBC_STATE_WRITE;
01288
01289
01290 lun->inquiryData->bAdditionalLength
01291 = (unsigned char) (commandState->length - 5);
01292 }
01293
01294
01295
01296 switch (commandState->state) {
01297
01298 case SBC_STATE_WRITE:
01299
01300
01301
01302 #if 1
01303 status = USBD_Write(commandState->pipeIN,
01304 (void *) lun->inquiryData,
01305 commandState->length,
01306 (TransferCallback) MSDDriver_Callback,
01307 (void *) transfer);
01308 #else
01309 status = MSDD_Write((void *) lun->inquiryData,
01310 commandState->length,
01311 (TransferCallback) MSDDriver_Callback,
01312 (void *) transfer);
01313 #endif
01314
01315
01316 if (status != USBD_STATUS_SUCCESS) {
01317
01318 TRACE_WARNING(
01319 "SPC_Inquiry: Cannot start sending data\n\r");
01320 result = MSDD_STATUS_ERROR;
01321 }
01322 else {
01323
01324
01325 TRACE_INFO_WP("Sending ");
01326 commandState->state = SBC_STATE_WAIT_WRITE;
01327 }
01328 break;
01329
01330
01331 case SBC_STATE_WAIT_WRITE:
01332
01333
01334
01335 if (transfer->semaphore > 0) {
01336
01337
01338 transfer->semaphore--;
01339
01340 if (transfer->status != USBD_STATUS_SUCCESS) {
01341
01342 TRACE_WARNING(
01343 "SPC_Inquiry: Data transfer failed\n\r");
01344 result = MSDD_STATUS_ERROR;
01345 }
01346 else {
01347
01348 TRACE_INFO_WP("Sent ");
01349 result = MSDD_STATUS_SUCCESS;
01350 }
01351
01352
01353 commandState->length -= transfer->transferred;
01354 }
01355 break;
01356 }
01357
01358 return result;
01359 }
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373 static unsigned char SBC_RequestSense(MSDLun *lun,
01374 MSDCommandState *commandState)
01375 {
01376 unsigned char result = MSDD_STATUS_INCOMPLETE;
01377 unsigned char status;
01378 MSDTransfer *transfer = &(commandState->transfer);
01379
01380
01381 if (commandState->length == 0) {
01382
01383
01384
01385 result = MSDD_STATUS_SUCCESS;
01386 }
01387
01388 else if (commandState->state == 0) {
01389
01390 commandState->state = SBC_STATE_WRITE;
01391 }
01392
01393
01394 switch (commandState->state) {
01395
01396 case SBC_STATE_WRITE:
01397
01398
01399
01400 #if 1
01401 status = USBD_Write(commandState->pipeIN,
01402 &(lun->requestSenseData),
01403 commandState->length,
01404 (TransferCallback) MSDDriver_Callback,
01405 (void *) transfer);
01406 #else
01407 status = MSDD_Write(&(lun->requestSenseData),
01408 commandState->length,
01409 (TransferCallback) MSDDriver_Callback,
01410 (void *) transfer);
01411 #endif
01412
01413
01414 if (status != USBD_STATUS_SUCCESS) {
01415
01416 TRACE_WARNING(
01417 "RBC_RequestSense: Cannot start sending data\n\r");
01418 result = MSDD_STATUS_ERROR;
01419 }
01420 else {
01421
01422
01423 commandState->state = SBC_STATE_WAIT_WRITE;
01424 }
01425 break;
01426
01427
01428 case SBC_STATE_WAIT_WRITE:
01429
01430
01431
01432 if (transfer->semaphore > 0) {
01433
01434
01435 transfer->semaphore--;
01436
01437 if (transfer->status != USBD_STATUS_SUCCESS) {
01438
01439 result = MSDD_STATUS_ERROR;
01440 }
01441 else {
01442
01443 result = MSDD_STATUS_SUCCESS;
01444 }
01445
01446
01447 commandState->length -= transfer->transferred;
01448 }
01449 break;
01450 }
01451
01452 return result;
01453 }
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466
01467 static unsigned char SBC_ModeSense6(MSDLun *lun, MSDCommandState *commandState)
01468 {
01469 unsigned char result = MSDD_STATUS_INCOMPLETE;
01470 unsigned char status;
01471 MSDTransfer *transfer = &(commandState->transfer);
01472 SBCCommand *pCmd = (SBCCommand*)commandState->cbw.pCommand;
01473
01474 if (!SBCLunIsReady(lun)) {
01475
01476 TRACE_INFO("SBC_ModeSense6: Not Ready!\n\r");
01477 return MSDD_STATUS_RW;
01478 }
01479
01480
01481 if (pCmd->modeSense6.bPageCode
01482 != SBC_PAGE_RETURN_ALL) {
01483
01484 return MSDD_STATUS_PARAMETER;
01485 }
01486
01487
01488 if (commandState->state == 0) {
01489
01490 commandState->state = SBC_STATE_WRITE;
01491 }
01492
01493
01494 switch (commandState->state) {
01495
01496 case SBC_STATE_WRITE:
01497
01498
01499
01500 #if 1
01501 status = USBD_Write(commandState->pipeIN,
01502 (void *) &modeParameterHeader6,
01503 commandState->length,
01504 (TransferCallback) MSDDriver_Callback,
01505 (void *) transfer);
01506 #else
01507 status = MSDD_Write((void *) &modeParameterHeader6,
01508 commandState->length,
01509 (TransferCallback) MSDDriver_Callback,
01510 (void *) transfer);
01511 #endif
01512
01513
01514 if (status != USBD_STATUS_SUCCESS) {
01515
01516 TRACE_WARNING(
01517 "SPC_ModeSense6: Cannot start data transfer\n\r");
01518 result = MSDD_STATUS_ERROR;
01519 }
01520 else {
01521
01522
01523 commandState->state = SBC_STATE_WAIT_WRITE;
01524 }
01525 break;
01526
01527
01528 case SBC_STATE_WAIT_WRITE:
01529
01530
01531 TRACE_INFO_WP("Wait ");
01532
01533
01534 if (transfer->semaphore > 0) {
01535
01536
01537 transfer->semaphore--;
01538
01539 if (transfer->status != USBD_STATUS_SUCCESS) {
01540
01541 TRACE_WARNING(
01542 "SPC_ModeSense6: Data transfer failed\n\r");
01543 result = MSDD_STATUS_ERROR;
01544 }
01545 else {
01546
01547 result = MSDD_STATUS_SUCCESS;
01548 }
01549
01550
01551 commandState->length -= transfer->transferred;
01552
01553 }
01554 break;
01555 }
01556
01557 return result;
01558 }
01559
01560
01561
01562
01563
01564
01565
01566 static unsigned char SBC_TestUnitReady(MSDLun *lun)
01567 {
01568 unsigned char result = MSDD_STATUS_RW;
01569 unsigned char senseKey = SBC_SENSE_KEY_NO_SENSE,
01570 addSenseCode = 0,
01571 addSenseCodeQual = 0;
01572
01573
01574
01575 if (lun->status < LUN_CHANGED) {
01576
01577 TRACE_INFO_WP("Ejc ");
01578 senseKey = SBC_SENSE_KEY_NOT_READY;
01579 addSenseCode = SBC_ASC_MEDIUM_NOT_PRESENT;
01580 }
01581 else if (lun->status == LUN_CHANGED) {
01582
01583 TRACE_INFO_WP("Chg ");
01584 senseKey = SBC_SENSE_KEY_UNIT_ATTENTION;
01585 addSenseCode = SBC_ASC_NOT_READY_TO_READY_CHANGE;
01586 lun->status = LUN_READY;
01587 }
01588 else {
01589
01590 switch(MED_GetState(lun->media)) {
01591
01592 case MED_STATE_READY:
01593
01594
01595
01596 TRACE_INFO_WP("Rdy ");
01597 result = MSDD_STATUS_SUCCESS;
01598 break;
01599
01600
01601 case MED_STATE_BUSY:
01602
01603
01604 TRACE_INFO_WP("Bsy ");
01605 senseKey = SBC_SENSE_KEY_NOT_READY;
01606 break;
01607
01608
01609 default:
01610
01611
01612 TRACE_INFO_WP("? ");
01613 senseKey = SBC_SENSE_KEY_NOT_READY;
01614 addSenseCode = SBC_ASC_MEDIUM_NOT_PRESENT;
01615 break;
01616 }
01617 }
01618 SBC_UpdateSenseData(&(lun->requestSenseData),
01619 senseKey,
01620 addSenseCode,
01621 addSenseCodeQual);
01622
01623 return result;
01624 }
01625
01626
01627
01628
01629
01630
01631
01632
01633
01634
01635
01636 void SBC_UpdateSenseData(SBCRequestSenseData *requestSenseData,
01637 unsigned char senseKey,
01638 unsigned char additionalSenseCode,
01639 unsigned char additionalSenseCodeQualifier)
01640 {
01641 requestSenseData->bSenseKey = senseKey;
01642 requestSenseData->bAdditionalSenseCode = additionalSenseCode;
01643 requestSenseData->bAdditionalSenseCodeQualifier
01644 = additionalSenseCodeQualifier;
01645 }
01646
01647
01648
01649
01650
01651
01652
01653
01654
01655 unsigned char SBC_GetCommandInformation(void *command,
01656 unsigned int *length,
01657 unsigned char *type,
01658 MSDLun *lun)
01659 {
01660 SBCCommand *sbcCommand = (SBCCommand *) command;
01661 unsigned char isCommandSupported = 1;
01662
01663
01664
01665 switch (sbcCommand->bOperationCode) {
01666
01667
01668 case SBC_INQUIRY:
01669
01670
01671 (*type) = MSDD_DEVICE_TO_HOST;
01672
01673
01674
01675 (*length) = WORDB(sbcCommand->inquiry.pAllocationLength);
01676 break;
01677
01678
01679
01680 case SBC_MODE_SENSE_6:
01681
01682
01683 (*type) = MSDD_DEVICE_TO_HOST;
01684 if (sbcCommand->modeSense6.bAllocationLength >
01685 sizeof(SBCModeParameterHeader6)) {
01686
01687 *length = sizeof(SBCModeParameterHeader6);
01688 }
01689 else {
01690
01691 *length = sbcCommand->modeSense6.bAllocationLength;
01692 }
01693 break;
01694
01695
01696
01697 case SBC_PREVENT_ALLOW_MEDIUM_REMOVAL:
01698
01699
01700 (*type) = MSDD_NO_TRANSFER;
01701 break;
01702
01703
01704
01705 case SBC_REQUEST_SENSE:
01706
01707
01708 (*type) = MSDD_DEVICE_TO_HOST;
01709 (*length) = sbcCommand->requestSense.bAllocationLength;
01710 break;
01711
01712
01713
01714 case SBC_TEST_UNIT_READY:
01715
01716
01717 (*type) = MSDD_NO_TRANSFER;
01718 break;
01719
01720
01721
01722 case SBC_READ_CAPACITY_10:
01723
01724
01725 (*type) = MSDD_DEVICE_TO_HOST;
01726 (*length) = sizeof(SBCReadCapacity10Data);
01727 break;
01728
01729
01730
01731 case SBC_READ_10:
01732
01733
01734 (*type) = MSDD_DEVICE_TO_HOST;
01735 (*length) = WORDB(sbcCommand->read10.pTransferLength)
01736 * lun->blockSize * MED_GetBlockSize(lun->media);
01737 break;
01738
01739
01740
01741 case SBC_WRITE_10:
01742
01743
01744 (*type) = MSDD_HOST_TO_DEVICE;
01745 (*length) = WORDB(sbcCommand->write10.pTransferLength)
01746 * lun->blockSize * MED_GetBlockSize(lun->media);
01747 break;
01748
01749
01750
01751 case SBC_VERIFY_10:
01752
01753
01754 (*type) = MSDD_NO_TRANSFER;
01755 break;
01756
01757
01758 default:
01759
01760
01761 isCommandSupported = 0;
01762 }
01763
01764
01765
01766 if ((*length) == 0) {
01767
01768 (*type) = MSDD_NO_TRANSFER;
01769 }
01770
01771 return isCommandSupported;
01772 }
01773
01774
01775
01776
01777
01778
01779
01780 unsigned char SBC_ProcessCommand(MSDLun *lun,
01781 MSDCommandState *commandState)
01782 {
01783 unsigned char result = MSDD_STATUS_INCOMPLETE;
01784 SBCCommand *command = (SBCCommand *) commandState->cbw.pCommand;
01785
01786
01787
01788 switch (command->bOperationCode) {
01789
01790 case SBC_READ_10:
01791
01792
01793
01794
01795
01796 result = SBC_Read10(lun, commandState);
01797 break;
01798
01799
01800 case SBC_WRITE_10:
01801
01802
01803
01804
01805
01806 result = SBC_Write10(lun, commandState);
01807 break;
01808
01809
01810 case SBC_READ_CAPACITY_10:
01811
01812
01813
01814
01815
01816 result = SBC_ReadCapacity10(lun, commandState);
01817 break;
01818
01819
01820 case SBC_VERIFY_10:
01821
01822
01823
01824
01825
01826 MED_Flush(lun->media);
01827 result = MSDD_STATUS_SUCCESS;
01828 break;
01829
01830
01831 case SBC_INQUIRY:
01832
01833
01834
01835
01836 result = SBC_Inquiry(lun, commandState);
01837 break;
01838
01839
01840 case SBC_MODE_SENSE_6:
01841
01842
01843 TRACE_INFO_WP("ModeSense(6) ");
01844
01845 result = SBC_ModeSense6(lun, commandState);
01846 break;
01847
01848
01849
01850 case SBC_TEST_UNIT_READY:
01851
01852
01853 TRACE_INFO_WP("TstUnitRdy ");
01854
01855
01856 result = SBC_TestUnitReady(lun);
01857 break;
01858
01859
01860 case SBC_REQUEST_SENSE:
01861
01862 TRACE_INFO_WP("ReqSense ");
01863
01864
01865 result = SBC_RequestSense(lun, commandState);
01866 break;
01867
01868
01869 case SBC_PREVENT_ALLOW_MEDIUM_REMOVAL:
01870
01871 TRACE_INFO_WP("PrevAllowRem ");
01872
01873
01874
01875 result = command->mediumRemoval.bPrevent ?
01876 MSDD_STATUS_PARAMETER : MSDD_STATUS_SUCCESS;
01877 break;
01878
01879
01880 case SBC_READ_FORMAT_CAPACITIES:
01881
01882
01883 result = MSDD_STATUS_PARAMETER;
01884 break;
01885
01886 default:
01887
01888 result = MSDD_STATUS_PARAMETER;
01889 }
01890
01891 return result;
01892 }
01893
01894