msdscsi.c

Go to the documentation of this file.
00001 /***************************************************************************/
00035 #include "em_usb.h"
00036 #include "msdscsi.h"
00037 #include "msdbot.h"
00038 
00041 /**************************************************************************/
00045 #define CBW_SCSI_READ10_INIT_DEFAULT                 \
00046   {                                                  \
00047     CBW_SIGNATURE,   /* CBW Signature, ascii USBC */ \
00048     0x78563412,      /* CBW Tag                   */ \
00049     0x00000000,      /* CBW Data Transfer Length  */ \
00050     { { 0, 0, 1 } }, /* CBW Flags                 */ \
00051     { { 0, 0 } },    /* CBW Lun                   */ \
00052     { { 10, 0 } },   /* CBW CBLength              */ \
00053     { SCSI_READ10,   /* CBW CB                    */ \
00054       0, 0, 0, 0,                                    \
00055       0, 0, 0, 0,                                    \
00056       0, 0, 0, 0,                                    \
00057       0, 0, 0 }                                      \
00058   }
00059 
00060 /**************************************************************************/
00064 #define CBW_SCSI_WRITE10_INIT_DEFAULT                \
00065   {                                                  \
00066     CBW_SIGNATURE,   /* CBW Signature, ascii USBC */ \
00067     0x78563412,      /* CBW Tag                   */ \
00068     0x00000000,      /* CBW Data Transfer Length  */ \
00069     { { 0, 0, 0 } }, /* CBW Flags                 */ \
00070     { { 0, 0 } },    /* CBW Lun                   */ \
00071     { { 10, 0 } },   /* CBW CBLength              */ \
00072     { SCSI_WRITE10,  /* CBW CB                    */ \
00073       0, 0, 0, 0,                                    \
00074       0, 0, 0, 0,                                    \
00075       0, 0, 0, 0,                                    \
00076       0, 0, 0 }                                      \
00077   }
00078 
00079 /**************************************************************************/
00083 EFM32_ALIGN(4)
00084 static const char cbwInquiry[ CBW_LEN ] __attribute__ ((aligned(4))) =
00085 {
00086   'U',          'S',                  'B',  'C',  /* CBW Signature                     */
00087   0x12,                         0x34, 0x56, 0x78, /* CBW Tag                           */
00088   SCSI_INQUIRYDATA_LEN,                           /* CBW Data Transfer Length          */
00089   0x00,                         0x00, 0x00,
00090   BOT_DIR_IN,                   0x00,    6,       /* CBW Flags, CBW Lun, CBW CB Length */
00091   SCSI_INQUIRY,                 0x00, 0x00,       /* 6 byte CBW CB                     */
00092   0x00,         SCSI_INQUIRYDATA_LEN,
00093   0x00,                         0x00, 0x00, 0x00,
00094   0x00,                         0x00, 0x00, 0x00,
00095   0x00,                         0x00, 0x00
00096 };
00097 
00098 /**************************************************************************/
00102 EFM32_ALIGN(4)
00103 static const char cbwReadCap[ CBW_LEN ] __attribute__ ((aligned(4))) =
00104 {
00105   'U',        'S',  'B',  'C',  /* CBW Signature                     */
00106   0x12,       0x34, 0x56, 0x78, /* CBW Tag                           */
00107   SCSI_READCAPACITYDATA_LEN,    /* CBW Data Transfer Length          */
00108   0x00,       0x00, 0x00,
00109   BOT_DIR_IN, 0x00,   10,       /* CBW Flags, CBW Lun, CBW CB Length */
00110   SCSI_READCAPACITY,            /* 10 byte CBW CB                    */
00111   0x00,       0x00, 0x00, 0x00,
00112   0x00,       0x00, 0x00, 0x00,
00113   0x00,       0x00, 0x00, 0x00,
00114   0x00,       0x00, 0x00
00115 };
00116 
00117 /**************************************************************************/
00121 EFM32_ALIGN(4)
00122 static const char cbwRs[ CBW_LEN ] __attribute__ ((aligned(4))) =
00123 {
00124   'U',                       'S',  'B',  'C',  /* CBW Signature                     */
00125   0x12,                      0x34, 0x56, 0x78, /* CBW Tag                           */
00126   SCSI_REQUESTSENSEDATA_LEN,                   /* CBW Data Transfer Length          */
00127   0x00,                      0x00, 0x00,
00128   BOT_DIR_IN,                0x00,    6,       /* CBW Flags, CBW Lun, CBW CB Length */
00129   SCSI_REQUESTSENSE,         0x00,             /* 6 byte CBW CB                     */
00130   0x00,                      0x00,
00131   SCSI_REQUESTSENSEDATA_LEN,
00132   0x00,                      0x00, 0x00, 0x00,
00133   0x00,                      0x00, 0x00, 0x00,
00134   0x00,                      0x00, 0x00
00135 };
00136 
00137 /**************************************************************************/
00141 EFM32_ALIGN(4)
00142 static const char cbwTur[ CBW_LEN ] __attribute__ ((aligned(4))) =
00143 {
00144   'U',                 'S',  'B',  'C',  /* CBW Signature                     */
00145   0x12,                0x34, 0x56, 0x78, /* CBW Tag                           */
00146   0x00,                0x00, 0x00, 0x00, /* CBW Data Transfer Length          */
00147   BOT_DIR_IN,          0x00,    6,       /* CBW Flags, CBW Lun, CBW CB Length */
00148   SCSI_TESTUNIT_READY, 0x00,             /* 6 byte CBW CB                     */
00149   0x00,                0x00, 0x00, 0x00,
00150   0x00,                0x00, 0x00, 0x00,
00151   0x00,                0x00, 0x00, 0x00,
00152   0x00, 0x00
00153 };
00154 
00155 
00156 /* Media properties. */
00157 static uint32_t lbaCount = 0;
00158 static uint32_t lbaSize  = 0;
00159 
00162 /***************************************************************************/
00175 bool MSDSCSI_Init(USBH_Ep_TypeDef *out, USBH_Ep_TypeDef *in)
00176 {
00177   /* Check if all typedef's are properly packed. */
00178 
00179   if ((sizeof(MSDSCSI_Read10_TypeDef) != SCSI_READ10_LEN) ||
00180       (sizeof(MSDSCSI_Write10_TypeDef) != SCSI_WRITE10_LEN) ||
00181       (sizeof(MSDSCSI_InquiryData_TypeDef) != SCSI_INQUIRYDATA_LEN) ||
00182       (sizeof(MSDSCSI_RequestSenseData_TypeDef) != SCSI_REQUESTSENSEDATA_LEN) ||
00183       (sizeof(MSDSCSI_ReadCapacityData_TypeDef) != SCSI_READCAPACITYDATA_LEN))
00184   {
00185     DEBUG_USB_API_PUTS("\nMSDSCSI_Init(), typedef size error");
00186     EFM_ASSERT(false);
00187     return false;
00188   }
00189 
00190   /* Initialize the Bulk-Only-Transport (BOT) module. */
00191   if (MSDBOT_Init(out, in) != MSDBOT_STATUS_OK)
00192     return false;
00193 
00194   return true;
00195 }
00196 
00197 /***************************************************************************/
00207 bool MSDSCSI_Inquiry(MSDSCSI_InquiryData_TypeDef *data)
00208 {
00209   if (MSDBOT_Xfer((void*) cbwInquiry, data) == SCSI_INQUIRYDATA_LEN)
00210     return true;
00211 
00212   return false;
00213 }
00214 
00215 /***************************************************************************/
00231 bool MSDSCSI_Read10(uint32_t lba, uint16_t sectors, void *data)
00232 {
00233   EFM32_ALIGN(4)
00234   MSDBOT_CBW_TypeDef cbw __attribute__ ((aligned(4))) = CBW_SCSI_READ10_INIT_DEFAULT;
00235 
00236   MSDSCSI_Read10_TypeDef *cb = (MSDSCSI_Read10_TypeDef*) &cbw.CBWCB;
00237 
00238   cbw.dCBWDataTransferLength = sectors * lbaSize;
00239   cb->Lba                    = __REV(lba);
00240   cb->TransferLength         = __REV16(sectors);
00241 
00242   if ((uint32_t) MSDBOT_Xfer(&cbw, data) == cbw.dCBWDataTransferLength)
00243     return true;
00244 
00245   return false;
00246 }
00247 
00248 /***************************************************************************/
00258 bool MSDSCSI_ReadCapacity(MSDSCSI_ReadCapacityData_TypeDef *data)
00259 {
00260   if (MSDBOT_Xfer((void*) cbwReadCap, data) == SCSI_READCAPACITYDATA_LEN)
00261   {
00262     /* Big to Little endian conversion, keep local copy of lba count and size */
00263     lbaCount = __REV(data->LogicalBlockAddress);
00264     lbaSize  = __REV(data->LogicalBlockLength);
00265 
00266     data->LogicalBlockAddress = lbaCount;
00267     data->LogicalBlockLength  = lbaSize;
00268 
00269     return true;
00270   }
00271 
00272   return false;
00273 }
00274 
00275 /***************************************************************************/
00285 bool MSDSCSI_RequestSense(MSDSCSI_RequestSenseData_TypeDef *data)
00286 {
00287   if (MSDBOT_Xfer((void*) cbwRs, data) == SCSI_REQUESTSENSEDATA_LEN)
00288     return true;
00289 
00290   return false;
00291 }
00292 
00293 /***************************************************************************/
00301 bool MSDSCSI_TestUnitReady(void)
00302 {
00303   if (MSDBOT_Xfer((void*) cbwTur, NULL) == MSDBOT_STATUS_OK)
00304     return true;
00305 
00306   return false;
00307 }
00308 
00309 /***************************************************************************/
00325 bool MSDSCSI_Write10(uint32_t lba, uint16_t sectors, const void *data)
00326 {
00327   EFM32_ALIGN(4)
00328   MSDBOT_CBW_TypeDef cbw __attribute__ ((aligned(4))) = CBW_SCSI_WRITE10_INIT_DEFAULT;
00329 
00330   MSDSCSI_Write10_TypeDef *cb = (MSDSCSI_Write10_TypeDef*) &cbw.CBWCB;
00331 
00332   cbw.dCBWDataTransferLength = sectors * lbaSize;
00333   cb->Lba                    = __REV(lba);
00334   cb->TransferLength         = __REV16(sectors);
00335 
00336   if ((uint32_t) MSDBOT_Xfer(&cbw, (void*) data) == cbw.dCBWDataTransferLength)
00337     return true;
00338 
00339   return false;
00340 }