EFM32 Gecko Software Documentation  efm32g-doc-5.1.2
msdscsi.c
Go to the documentation of this file.
1 /***************************************************************************/
17 #include "em_usb.h"
18 #include "msdscsi.h"
19 #include "msdbot.h"
20 
23 /**************************************************************************/
27 #define CBW_SCSI_READ10_INIT_DEFAULT \
28  { \
29  CBW_SIGNATURE, /* CBW Signature, ascii USBC */ \
30  0x78563412, /* CBW Tag */ \
31  0x00000000, /* CBW Data Transfer Length */ \
32  { { 0, 0, 1 } }, /* CBW Flags */ \
33  { { 0, 0 } }, /* CBW Lun */ \
34  { { 10, 0 } }, /* CBW CBLength */ \
35  { SCSI_READ10, /* CBW CB */ \
36  0, 0, 0, 0, \
37  0, 0, 0, 0, \
38  0, 0, 0, 0, \
39  0, 0, 0 } \
40  }
41 
42 /**************************************************************************/
46 #define CBW_SCSI_WRITE10_INIT_DEFAULT \
47  { \
48  CBW_SIGNATURE, /* CBW Signature, ascii USBC */ \
49  0x78563412, /* CBW Tag */ \
50  0x00000000, /* CBW Data Transfer Length */ \
51  { { 0, 0, 0 } }, /* CBW Flags */ \
52  { { 0, 0 } }, /* CBW Lun */ \
53  { { 10, 0 } }, /* CBW CBLength */ \
54  { SCSI_WRITE10, /* CBW CB */ \
55  0, 0, 0, 0, \
56  0, 0, 0, 0, \
57  0, 0, 0, 0, \
58  0, 0, 0 } \
59  }
60 
61 /**************************************************************************/
65 SL_ALIGN(4)
66 static const char cbwInquiry[ CBW_LEN ] SL_ATTRIBUTE_ALIGN(4) =
67 {
68  'U', 'S', 'B', 'C', /* CBW Signature */
69  0x12, 0x34, 0x56, 0x78, /* CBW Tag */
70  SCSI_INQUIRYDATA_LEN, /* CBW Data Transfer Length */
71  0x00, 0x00, 0x00,
72  BOT_DIR_IN, 0x00, 6, /* CBW Flags, CBW Lun, CBW CB Length */
73  SCSI_INQUIRY, 0x00, 0x00, /* 6 byte CBW CB */
75  0x00, 0x00, 0x00, 0x00,
76  0x00, 0x00, 0x00, 0x00,
77  0x00, 0x00, 0x00
78 };
79 
80 /**************************************************************************/
84 SL_ALIGN(4)
85 static const char cbwReadCap[ CBW_LEN ] SL_ATTRIBUTE_ALIGN(4) =
86 {
87  'U', 'S', 'B', 'C', /* CBW Signature */
88  0x12, 0x34, 0x56, 0x78, /* CBW Tag */
89  SCSI_READCAPACITYDATA_LEN, /* CBW Data Transfer Length */
90  0x00, 0x00, 0x00,
91  BOT_DIR_IN, 0x00, 10, /* CBW Flags, CBW Lun, CBW CB Length */
92  SCSI_READCAPACITY, /* 10 byte CBW CB */
93  0x00, 0x00, 0x00, 0x00,
94  0x00, 0x00, 0x00, 0x00,
95  0x00, 0x00, 0x00, 0x00,
96  0x00, 0x00, 0x00
97 };
98 
99 /**************************************************************************/
103 SL_ALIGN(4)
104 static const char cbwRs[ CBW_LEN ] SL_ATTRIBUTE_ALIGN(4) =
105 {
106  'U', 'S', 'B', 'C', /* CBW Signature */
107  0x12, 0x34, 0x56, 0x78, /* CBW Tag */
108  SCSI_REQUESTSENSEDATA_LEN, /* CBW Data Transfer Length */
109  0x00, 0x00, 0x00,
110  BOT_DIR_IN, 0x00, 6, /* CBW Flags, CBW Lun, CBW CB Length */
111  SCSI_REQUESTSENSE, 0x00, /* 6 byte CBW CB */
112  0x00, 0x00,
114  0x00, 0x00, 0x00, 0x00,
115  0x00, 0x00, 0x00, 0x00,
116  0x00, 0x00, 0x00
117 };
118 
119 /**************************************************************************/
123 SL_ALIGN(4)
124 static const char cbwTur[ CBW_LEN ] SL_ATTRIBUTE_ALIGN(4) =
125 {
126  'U', 'S', 'B', 'C', /* CBW Signature */
127  0x12, 0x34, 0x56, 0x78, /* CBW Tag */
128  0x00, 0x00, 0x00, 0x00, /* CBW Data Transfer Length */
129  BOT_DIR_IN, 0x00, 6, /* CBW Flags, CBW Lun, CBW CB Length */
130  SCSI_TESTUNIT_READY, 0x00, /* 6 byte CBW CB */
131  0x00, 0x00, 0x00, 0x00,
132  0x00, 0x00, 0x00, 0x00,
133  0x00, 0x00, 0x00, 0x00,
134  0x00, 0x00
135 };
136 
137 
138 /* Media properties. */
139 static uint32_t lbaCount = 0;
140 static uint32_t lbaSize = 0;
141 
144 /***************************************************************************/
157 bool MSDSCSI_Init(USBH_Ep_TypeDef *out, USBH_Ep_TypeDef *in)
158 {
159  /* Check if all typedef's are properly packed. */
160 
161  if ((sizeof(MSDSCSI_Read10_TypeDef) != SCSI_READ10_LEN) ||
166  {
167  DEBUG_USB_API_PUTS("\nMSDSCSI_Init(), typedef size error");
168  EFM_ASSERT(false);
169  return false;
170  }
171 
172  /* Initialize the Bulk-Only-Transport (BOT) module. */
173  if (MSDBOT_Init(out, in) != MSDBOT_STATUS_OK)
174  return false;
175 
176  return true;
177 }
178 
179 /***************************************************************************/
190 {
191  if (MSDBOT_Xfer((void*) cbwInquiry, data) == SCSI_INQUIRYDATA_LEN)
192  return true;
193 
194  return false;
195 }
196 
197 /***************************************************************************/
213 bool MSDSCSI_Read10(uint32_t lba, uint16_t sectors, void *data)
214 {
215  SL_ALIGN(4)
216  MSDBOT_CBW_TypeDef cbw SL_ATTRIBUTE_ALIGN(4) = CBW_SCSI_READ10_INIT_DEFAULT;
217 
219 
220  cbw.dCBWDataTransferLength = sectors * lbaSize;
221  cb->Lba = __REV(lba);
222  cb->TransferLength = __REV16(sectors);
223 
224  if ((uint32_t) MSDBOT_Xfer(&cbw, data) == cbw.dCBWDataTransferLength)
225  return true;
226 
227  return false;
228 }
229 
230 /***************************************************************************/
241 {
242  if (MSDBOT_Xfer((void*) cbwReadCap, data) == SCSI_READCAPACITYDATA_LEN)
243  {
244  /* Big to Little endian conversion, keep local copy of lba count and size */
245  lbaCount = __REV(data->LogicalBlockAddress);
246  lbaSize = __REV(data->LogicalBlockLength);
247 
248  data->LogicalBlockAddress = lbaCount;
249  data->LogicalBlockLength = lbaSize;
250 
251  return true;
252  }
253 
254  return false;
255 }
256 
257 /***************************************************************************/
268 {
269  if (MSDBOT_Xfer((void*) cbwRs, data) == SCSI_REQUESTSENSEDATA_LEN)
270  return true;
271 
272  return false;
273 }
274 
275 /***************************************************************************/
284 {
285  if (MSDBOT_Xfer((void*) cbwTur, NULL) == MSDBOT_STATUS_OK)
286  return true;
287 
288  return false;
289 }
290 
291 /***************************************************************************/
307 bool MSDSCSI_Write10(uint32_t lba, uint16_t sectors, const void *data)
308 {
309  SL_ALIGN(4)
310  MSDBOT_CBW_TypeDef cbw SL_ATTRIBUTE_ALIGN(4) = CBW_SCSI_WRITE10_INIT_DEFAULT;
311 
313 
314  cbw.dCBWDataTransferLength = sectors * lbaSize;
315  cb->Lba = __REV(lba);
316  cb->TransferLength = __REV16(sectors);
317 
318  if ((uint32_t) MSDBOT_Xfer(&cbw, (void*) data) == cbw.dCBWDataTransferLength)
319  return true;
320 
321  return false;
322 }
bool MSDSCSI_TestUnitReady(void)
Issue a SCSI Test Unit Ready command.
Definition: msdscsi.c:283
#define SCSI_TESTUNIT_READY
Definition: msdscsi.h:34
SCSI Inquiry response data typedef.
Definition: msdscsi.h:76
#define SCSI_REQUESTSENSEDATA_LEN
Definition: msdscsi.h:49
SCSI Request Sense response data typedef.
Definition: msdscsi.h:155
#define SL_ALIGN(X)
Macro for aligning a variable. Use this macro before the variable definition. X denotes the stora...
Definition: em_common.h:168
SCSI Read Capacity response data typedef.
Definition: msdscsi.h:214
#define SCSI_WRITE10_LEN
Definition: msdscsi.h:44
uint16_t TransferLength
Definition: msdscsi.h:243
bool MSDSCSI_Write10(uint32_t lba, uint16_t sectors, const void *data)
Perform a SCSI Write(10) command.
Definition: msdscsi.c:307
SCSI interface for Mass Storage Devices (MSD).
#define SCSI_READCAPACITY
Definition: msdscsi.h:38
#define SCSI_READ10_LEN
Definition: msdscsi.h:43
int MSDBOT_Xfer(void *cbw, void *data)
Perform an MSD Bulk Only Transfer (BOT).
Definition: msdbot.c:98
int MSDBOT_Init(USBH_Ep_TypeDef *out, USBH_Ep_TypeDef *in)
MSDBOT module initialization.
Definition: msdbot.c:58
#define SL_ATTRIBUTE_ALIGN(X)
GCC style macro for aligning a variable.
Definition: em_common.h:160
Definitions for the Bulk Only Transport protocol of USB Mass Storage devices.
SCSI Read 10 Command Descriptor Block (CDB) typedef.
Definition: msdscsi.h:225
bool MSDSCSI_RequestSense(MSDSCSI_RequestSenseData_TypeDef *data)
Issue a SCSI Request Sense command.
Definition: msdscsi.c:267
#define SCSI_READCAPACITYDATA_LEN
Definition: msdscsi.h:51
Bulk Only Transport (BOT) Command Block Wrapper (CBW) typedef.
Definition: msdbot.h:52
#define SCSI_INQUIRYDATA_LEN
Definition: msdscsi.h:46
SCSI Write 10 Command Descriptor Block (CDB) typedef.
Definition: msdscsi.h:252
#define SCSI_INQUIRY
Definition: msdscsi.h:36
bool MSDSCSI_Init(USBH_Ep_TypeDef *out, USBH_Ep_TypeDef *in)
MSDSCSI module initialization.
Definition: msdscsi.c:157
#define SCSI_REQUESTSENSE
Definition: msdscsi.h:35
bool MSDSCSI_Read10(uint32_t lba, uint16_t sectors, void *data)
Issue a SCSI Read(10) command.
Definition: msdscsi.c:213
bool MSDSCSI_ReadCapacity(MSDSCSI_ReadCapacityData_TypeDef *data)
Issue a SCSI Read Capacity command.
Definition: msdscsi.c:240
uint16_t TransferLength
Definition: msdscsi.h:270
bool MSDSCSI_Inquiry(MSDSCSI_InquiryData_TypeDef *data)
Issue a SCSI Inquiry command.
Definition: msdscsi.c:189