00001
00017 #include "em_usb.h"
00018 #include "msdscsi.h"
00019 #include "msdbot.h"
00020
00023
00027 #define CBW_SCSI_READ10_INIT_DEFAULT \
00028 { \
00029 CBW_SIGNATURE, \
00030 0x78563412, \
00031 0x00000000, \
00032 { { 0, 0, 1 } }, \
00033 { { 0, 0 } }, \
00034 { { 10, 0 } }, \
00035 { SCSI_READ10, \
00036 0, 0, 0, 0, \
00037 0, 0, 0, 0, \
00038 0, 0, 0, 0, \
00039 0, 0, 0 } \
00040 }
00041
00042
00046 #define CBW_SCSI_WRITE10_INIT_DEFAULT \
00047 { \
00048 CBW_SIGNATURE, \
00049 0x78563412, \
00050 0x00000000, \
00051 { { 0, 0, 0 } }, \
00052 { { 0, 0 } }, \
00053 { { 10, 0 } }, \
00054 { SCSI_WRITE10, \
00055 0, 0, 0, 0, \
00056 0, 0, 0, 0, \
00057 0, 0, 0, 0, \
00058 0, 0, 0 } \
00059 }
00060
00061
00065 EFM32_ALIGN(4)
00066 static const char cbwInquiry[ CBW_LEN ] __attribute__ ((aligned(4))) =
00067 {
00068 'U', 'S', 'B', 'C',
00069 0x12, 0x34, 0x56, 0x78,
00070 SCSI_INQUIRYDATA_LEN,
00071 0x00, 0x00, 0x00,
00072 BOT_DIR_IN, 0x00, 6,
00073 SCSI_INQUIRY, 0x00, 0x00,
00074 0x00, SCSI_INQUIRYDATA_LEN,
00075 0x00, 0x00, 0x00, 0x00,
00076 0x00, 0x00, 0x00, 0x00,
00077 0x00, 0x00, 0x00
00078 };
00079
00080
00084 EFM32_ALIGN(4)
00085 static const char cbwReadCap[ CBW_LEN ] __attribute__ ((aligned(4))) =
00086 {
00087 'U', 'S', 'B', 'C',
00088 0x12, 0x34, 0x56, 0x78,
00089 SCSI_READCAPACITYDATA_LEN,
00090 0x00, 0x00, 0x00,
00091 BOT_DIR_IN, 0x00, 10,
00092 SCSI_READCAPACITY,
00093 0x00, 0x00, 0x00, 0x00,
00094 0x00, 0x00, 0x00, 0x00,
00095 0x00, 0x00, 0x00, 0x00,
00096 0x00, 0x00, 0x00
00097 };
00098
00099
00103 EFM32_ALIGN(4)
00104 static const char cbwRs[ CBW_LEN ] __attribute__ ((aligned(4))) =
00105 {
00106 'U', 'S', 'B', 'C',
00107 0x12, 0x34, 0x56, 0x78,
00108 SCSI_REQUESTSENSEDATA_LEN,
00109 0x00, 0x00, 0x00,
00110 BOT_DIR_IN, 0x00, 6,
00111 SCSI_REQUESTSENSE, 0x00,
00112 0x00, 0x00,
00113 SCSI_REQUESTSENSEDATA_LEN,
00114 0x00, 0x00, 0x00, 0x00,
00115 0x00, 0x00, 0x00, 0x00,
00116 0x00, 0x00, 0x00
00117 };
00118
00119
00123 EFM32_ALIGN(4)
00124 static const char cbwTur[ CBW_LEN ] __attribute__ ((aligned(4))) =
00125 {
00126 'U', 'S', 'B', 'C',
00127 0x12, 0x34, 0x56, 0x78,
00128 0x00, 0x00, 0x00, 0x00,
00129 BOT_DIR_IN, 0x00, 6,
00130 SCSI_TESTUNIT_READY, 0x00,
00131 0x00, 0x00, 0x00, 0x00,
00132 0x00, 0x00, 0x00, 0x00,
00133 0x00, 0x00, 0x00, 0x00,
00134 0x00, 0x00
00135 };
00136
00137
00138
00139 static uint32_t lbaCount = 0;
00140 static uint32_t lbaSize = 0;
00141
00144
00157 bool MSDSCSI_Init(USBH_Ep_TypeDef *out, USBH_Ep_TypeDef *in)
00158 {
00159
00160
00161 if ((sizeof(MSDSCSI_Read10_TypeDef) != SCSI_READ10_LEN) ||
00162 (sizeof(MSDSCSI_Write10_TypeDef) != SCSI_WRITE10_LEN) ||
00163 (sizeof(MSDSCSI_InquiryData_TypeDef) != SCSI_INQUIRYDATA_LEN) ||
00164 (sizeof(MSDSCSI_RequestSenseData_TypeDef) != SCSI_REQUESTSENSEDATA_LEN) ||
00165 (sizeof(MSDSCSI_ReadCapacityData_TypeDef) != SCSI_READCAPACITYDATA_LEN))
00166 {
00167 DEBUG_USB_API_PUTS("\nMSDSCSI_Init(), typedef size error");
00168 EFM_ASSERT(false);
00169 return false;
00170 }
00171
00172
00173 if (MSDBOT_Init(out, in) != MSDBOT_STATUS_OK)
00174 return false;
00175
00176 return true;
00177 }
00178
00179
00189 bool MSDSCSI_Inquiry(MSDSCSI_InquiryData_TypeDef *data)
00190 {
00191 if (MSDBOT_Xfer((void*) cbwInquiry, data) == SCSI_INQUIRYDATA_LEN)
00192 return true;
00193
00194 return false;
00195 }
00196
00197
00213 bool MSDSCSI_Read10(uint32_t lba, uint16_t sectors, void *data)
00214 {
00215 EFM32_ALIGN(4)
00216 MSDBOT_CBW_TypeDef cbw __attribute__ ((aligned(4))) = CBW_SCSI_READ10_INIT_DEFAULT;
00217
00218 MSDSCSI_Read10_TypeDef *cb = (MSDSCSI_Read10_TypeDef*) &cbw.CBWCB;
00219
00220 cbw.dCBWDataTransferLength = sectors * lbaSize;
00221 cb->Lba = __REV(lba);
00222 cb->TransferLength = __REV16(sectors);
00223
00224 if ((uint32_t) MSDBOT_Xfer(&cbw, data) == cbw.dCBWDataTransferLength)
00225 return true;
00226
00227 return false;
00228 }
00229
00230
00240 bool MSDSCSI_ReadCapacity(MSDSCSI_ReadCapacityData_TypeDef *data)
00241 {
00242 if (MSDBOT_Xfer((void*) cbwReadCap, data) == SCSI_READCAPACITYDATA_LEN)
00243 {
00244
00245 lbaCount = __REV(data->LogicalBlockAddress);
00246 lbaSize = __REV(data->LogicalBlockLength);
00247
00248 data->LogicalBlockAddress = lbaCount;
00249 data->LogicalBlockLength = lbaSize;
00250
00251 return true;
00252 }
00253
00254 return false;
00255 }
00256
00257
00267 bool MSDSCSI_RequestSense(MSDSCSI_RequestSenseData_TypeDef *data)
00268 {
00269 if (MSDBOT_Xfer((void*) cbwRs, data) == SCSI_REQUESTSENSEDATA_LEN)
00270 return true;
00271
00272 return false;
00273 }
00274
00275
00283 bool MSDSCSI_TestUnitReady(void)
00284 {
00285 if (MSDBOT_Xfer((void*) cbwTur, NULL) == MSDBOT_STATUS_OK)
00286 return true;
00287
00288 return false;
00289 }
00290
00291
00307 bool MSDSCSI_Write10(uint32_t lba, uint16_t sectors, const void *data)
00308 {
00309 EFM32_ALIGN(4)
00310 MSDBOT_CBW_TypeDef cbw __attribute__ ((aligned(4))) = CBW_SCSI_WRITE10_INIT_DEFAULT;
00311
00312 MSDSCSI_Write10_TypeDef *cb = (MSDSCSI_Write10_TypeDef*) &cbw.CBWCB;
00313
00314 cbw.dCBWDataTransferLength = sectors * lbaSize;
00315 cb->Lba = __REV(lba);
00316 cb->TransferLength = __REV16(sectors);
00317
00318 if ((uint32_t) MSDBOT_Xfer(&cbw, (void*) data) == cbw.dCBWDataTransferLength)
00319 return true;
00320
00321 return false;
00322 }