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