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
00040 #include "MSDLun.h"
00041 #include <USBLib_Trace.h>
00042 #include "USBD.h"
00043
00044
00045
00046
00047
00048
00049 #define DEFAULT_LUN_BLOCK_SIZE 512
00050
00051
00052
00053
00054
00055
00056 static SBCInquiryData inquiryData = {
00057
00058 SBC_DIRECT_ACCESS_BLOCK_DEVICE,
00059 SBC_PERIPHERAL_DEVICE_CONNECTED,
00060 0x00,
00061 0x01,
00062 SBC_SPC_VERSION_4,
00063 0x2,
00064 0,
00065 0,
00066 0x0,
00067 sizeof(SBCInquiryData) - 5,
00068 0,
00069 0,
00070 SBC_TPGS_NONE,
00071 0,
00072 0x0,
00073 0,
00074 0x0,
00075 0,
00076 0x0,
00077 0,
00078 0x0,
00079 0x0,
00080 0x0,
00081 0,
00082 0x0,
00083 {'A','T','M','E','L',' ',' ',' '},
00084 {'M','a','s','s',' ',
00085 'S','t','o','r','a','g','e',' ',
00086 'M','S','D'},
00087 {'0','.','0','1'},
00088 {'M','a','s','s',' ',
00089 'S','t','o','r','a','g','e',' ',
00090 'E','x','a','m','p','l','e'},
00091 0x00,
00092 0x00,
00093 {SBC_VERSION_DESCRIPTOR_SBC_3},
00094 {0, 0, 0, 0, 0,
00095 0, 0, 0, 0, 0,
00096 0, 0, 0, 0, 0,
00097 0, 0, 0, 0, 0,
00098 0, 0}
00099 };
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122 void LUN_Init(MSDLun *lun,
00123 void *media,
00124 uint8_t *ioBuffer,
00125 uint32_t ioBufferSize,
00126 uint32_t baseAddress,
00127 uint32_t size,
00128 uint16_t blockSize,
00129 uint8_t protected,
00130 void (*dataMonitor)(uint8_t flowDirection,
00131 uint32_t dataLength,
00132 uint32_t fifoNullCount,
00133 uint32_t fifoFullCount))
00134 {
00135 uint32_t logicalBlockAddress;
00136 TRACE_INFO("LUN init\n\r");
00137
00138
00139
00140 lun->inquiryData = &inquiryData;
00141
00142
00143
00144 lun->requestSenseData.bResponseCode = SBC_SENSE_DATA_FIXED_CURRENT;
00145 lun->requestSenseData.isValid = 1;
00146 lun->requestSenseData.bObsolete1 = 0;
00147 lun->requestSenseData.bSenseKey = SBC_SENSE_KEY_NO_SENSE;
00148 lun->requestSenseData.bReserved1 = 0;
00149 lun->requestSenseData.isILI = 0;
00150 lun->requestSenseData.isEOM = 0;
00151 lun->requestSenseData.isFilemark = 0;
00152 lun->requestSenseData.pInformation[0] = 0;
00153 lun->requestSenseData.pInformation[1] = 0;
00154 lun->requestSenseData.pInformation[2] = 0;
00155 lun->requestSenseData.pInformation[3] = 0;
00156 lun->requestSenseData.bAdditionalSenseLength
00157 = sizeof(SBCRequestSenseData) - 8;
00158 lun->requestSenseData.bAdditionalSenseCode = 0;
00159 lun->requestSenseData.bAdditionalSenseCodeQualifier = 0;
00160 lun->requestSenseData.bFieldReplaceableUnitCode = 0;
00161 lun->requestSenseData.bSenseKeySpecific = 0;
00162 lun->requestSenseData.pSenseKeySpecific[0] = 0;
00163 lun->requestSenseData.pSenseKeySpecific[0] = 0;
00164 lun->requestSenseData.isSKSV = 0;
00165
00166 STORE_DWORDB(0, lun->readCapacityData.pLogicalBlockAddress);
00167 STORE_DWORDB(0, lun->readCapacityData.pLogicalBlockLength);
00168
00169
00170
00171 lun->media = media;
00172 if (media == 0) {
00173 lun->status = LUN_NOT_PRESENT;
00174 return;
00175 }
00176
00177 lun->baseAddress = baseAddress;
00178
00179
00180
00181 if (blockSize) {
00182 lun->blockSize = blockSize;
00183 }
00184 else {
00185 uint32_t blkSize = MED_GetBlockSize(media);
00186 if (blkSize < DEFAULT_LUN_BLOCK_SIZE)
00187 lun->blockSize = DEFAULT_LUN_BLOCK_SIZE / blkSize;
00188 else
00189 lun->blockSize = 1;
00190 }
00191
00192 if (size) {
00193 lun->size = size;
00194 }
00195 else {
00196 lun->size = MED_GetSize(media);
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213 }
00214
00215 TRACE_INFO("LUN: blkSize %d, size %d\n\r", (int)lun->blockSize, (int)lun->size);
00216 if (protected) lun->protected = 1;
00217 else lun->protected = MED_IsProtected(media);
00218
00219 MSDIOFifo_Init(&lun->ioFifo, ioBuffer, ioBufferSize);
00220
00221 lun->dataMonitor = dataMonitor;
00222
00223
00224
00225 logicalBlockAddress = lun->size / lun->blockSize - 1;
00226 STORE_DWORDB(logicalBlockAddress,
00227 lun->readCapacityData.pLogicalBlockAddress);
00228 STORE_DWORDB(lun->blockSize * MED_GetBlockSize(media),
00229 lun->readCapacityData.pLogicalBlockLength);
00230
00231
00232
00233 lun->status = LUN_CHANGED;
00234 }
00235
00236
00237
00238
00239
00240
00241 uint32_t LUN_Eject(MSDLun *lun)
00242 {
00243 if (lun->media) {
00244
00245
00246 if (MED_IsBusy(lun->media)) {
00247
00248 return USBD_STATUS_LOCKED;
00249 }
00250
00251
00252 lun->media = 0;
00253 }
00254
00255 lun->status = LUN_NOT_PRESENT;
00256
00257 return USBD_STATUS_SUCCESS;
00258 }
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270 uint32_t LUN_Write(MSDLun *lun,
00271 uint32_t blockAddress,
00272 void *data,
00273 uint32_t length,
00274 TransferCallback callback,
00275 void *argument)
00276 {
00277 uint32_t medBlk, medLen;
00278 uint8_t status;
00279
00280 TRACE_INFO_WP("LUNWrite(%u) ", blockAddress);
00281
00282
00283 if ((length + blockAddress) * lun->blockSize > lun->size) {
00284
00285 TRACE_WARNING("LUN_Write: Data too big\n\r");
00286 status = USBD_STATUS_ABORTED;
00287 }
00288 else if (lun->media == 0 || lun->status != LUN_READY) {
00289
00290 TRACE_WARNING("LUN_Write: Media not ready\n\r");
00291 status = USBD_STATUS_ABORTED;
00292 }
00293 else if (lun->protected) {
00294 TRACE_WARNING("LUN_Write: LUN is readonly\n\r");
00295 status = USBD_STATUS_ABORTED;
00296 }
00297 else {
00298
00299
00300 medBlk = lun->baseAddress + blockAddress * lun->blockSize;
00301 medLen = length * lun->blockSize;
00302
00303
00304 status = MED_Write(lun->media,
00305 medBlk,
00306 data,
00307 medLen,
00308 (fMEDCallback)callback,
00309 argument);
00310
00311
00312 if (status == MED_STATUS_SUCCESS) {
00313
00314 status = USBD_STATUS_SUCCESS;
00315 }
00316 else {
00317
00318 TRACE_WARNING("LUN_Write: Cannot write media\n\r");
00319 status = USBD_STATUS_ABORTED;
00320 }
00321 }
00322
00323 return status;
00324 }
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336 uint32_t LUN_Read(MSDLun *lun,
00337 uint32_t blockAddress,
00338 void *data,
00339 uint32_t length,
00340 TransferCallback callback,
00341 void *argument)
00342 {
00343 uint32_t medBlk, medLen;
00344 uint8_t status;
00345
00346
00347 if ((length + blockAddress) * lun->blockSize > lun->size) {
00348
00349 TRACE_WARNING("LUN_Read: Area: (%d + %d)*%d > %d\n\r",
00350 (int)length, (int)blockAddress, (int)lun->blockSize, (int)lun->size);
00351 status = USBD_STATUS_ABORTED;
00352 }
00353 else if (lun->media == 0 || lun->status != LUN_READY) {
00354
00355 TRACE_WARNING("LUN_Read: Media not present\n\r");
00356 status = USBD_STATUS_ABORTED;
00357 }
00358 else {
00359
00360 TRACE_INFO_WP("LUNRead(%u) ", blockAddress);
00361
00362
00363 medBlk = lun->baseAddress + (blockAddress * lun->blockSize);
00364 medLen = length * lun->blockSize;
00365
00366
00367 status = MED_Read(lun->media,
00368 medBlk,
00369 data,
00370 medLen,
00371 (fMEDCallback)callback,
00372 argument);
00373
00374
00375 if (status == MED_STATUS_SUCCESS) {
00376
00377 status = USBD_STATUS_SUCCESS;
00378 }
00379 else {
00380
00381 TRACE_WARNING("LUN_Read: Cannot read media\n\r");
00382 status = USBD_STATUS_ABORTED;
00383 }
00384 }
00385
00386 return status;
00387 }
00388
00389