msdscsi.c

Go to the documentation of this file.
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,   /* CBW Signature, ascii USBC */ \
00030     0x78563412,      /* CBW Tag                   */ \
00031     0x00000000,      /* CBW Data Transfer Length  */ \
00032     { { 0, 0, 1 } }, /* CBW Flags                 */ \
00033     { { 0, 0 } },    /* CBW Lun                   */ \
00034     { { 10, 0 } },   /* CBW CBLength              */ \
00035     { SCSI_READ10,   /* CBW CB                    */ \
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,   /* CBW Signature, ascii USBC */ \
00049     0x78563412,      /* CBW Tag                   */ \
00050     0x00000000,      /* CBW Data Transfer Length  */ \
00051     { { 0, 0, 0 } }, /* CBW Flags                 */ \
00052     { { 0, 0 } },    /* CBW Lun                   */ \
00053     { { 10, 0 } },   /* CBW CBLength              */ \
00054     { SCSI_WRITE10,  /* CBW CB                    */ \
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',  /* CBW Signature                     */
00069   0x12,                         0x34, 0x56, 0x78, /* CBW Tag                           */
00070   SCSI_INQUIRYDATA_LEN,                           /* CBW Data Transfer Length          */
00071   0x00,                         0x00, 0x00,
00072   BOT_DIR_IN,                   0x00,    6,       /* CBW Flags, CBW Lun, CBW CB Length */
00073   SCSI_INQUIRY,                 0x00, 0x00,       /* 6 byte CBW CB                     */
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',  /* CBW Signature                     */
00088   0x12,       0x34, 0x56, 0x78, /* CBW Tag                           */
00089   SCSI_READCAPACITYDATA_LEN,    /* CBW Data Transfer Length          */
00090   0x00,       0x00, 0x00,
00091   BOT_DIR_IN, 0x00,   10,       /* CBW Flags, CBW Lun, CBW CB Length */
00092   SCSI_READCAPACITY,            /* 10 byte CBW CB                    */
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',  /* CBW Signature                     */
00107   0x12,                      0x34, 0x56, 0x78, /* CBW Tag                           */
00108   SCSI_REQUESTSENSEDATA_LEN,                   /* CBW Data Transfer Length          */
00109   0x00,                      0x00, 0x00,
00110   BOT_DIR_IN,                0x00,    6,       /* CBW Flags, CBW Lun, CBW CB Length */
00111   SCSI_REQUESTSENSE,         0x00,             /* 6 byte CBW CB                     */
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',  /* CBW Signature                     */
00127   0x12,                0x34, 0x56, 0x78, /* CBW Tag                           */
00128   0x00,                0x00, 0x00, 0x00, /* CBW Data Transfer Length          */
00129   BOT_DIR_IN,          0x00,    6,       /* CBW Flags, CBW Lun, CBW CB Length */
00130   SCSI_TESTUNIT_READY, 0x00,             /* 6 byte CBW CB                     */
00131   0x00,                0x00, 0x00, 0x00,
00132   0x00,                0x00, 0x00, 0x00,
00133   0x00,                0x00, 0x00, 0x00,
00134   0x00, 0x00
00135 };
00136 
00137 
00138 /* Media properties. */
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   /* Check if all typedef's are properly packed. */
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   /* Initialize the Bulk-Only-Transport (BOT) module. */
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     /* Big to Little endian conversion, keep local copy of lba count and size */
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 }