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