usbhscsi.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823
  1. //*****************************************************************************
  2. //
  3. // usbhscsi.c - USB host SCSI layer used by the USB host MSC driver.
  4. //
  5. // Copyright (c) 2008-2010 Texas Instruments Incorporated. All rights reserved.
  6. // Software License Agreement
  7. //
  8. // Texas Instruments (TI) is supplying this software for use solely and
  9. // exclusively on TI's microcontroller products. The software is owned by
  10. // TI and/or its suppliers, and is protected under applicable copyright
  11. // laws. You may not combine this software with "viral" open-source
  12. // software in order to form a larger program.
  13. //
  14. // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
  15. // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
  16. // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  17. // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
  18. // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
  19. // DAMAGES, FOR ANY REASON WHATSOEVER.
  20. //
  21. // This is part of AM1808 StarterWare USB Library, resused from revision 6288 of the
  22. // stellaris USB Library.
  23. //
  24. //*****************************************************************************
  25. #include "hw_types.h"
  26. #include "usblib.h"
  27. #include "usbmsc.h"
  28. #include "usbhost.h"
  29. #include "usbhmsc.h"
  30. #include "usbhscsi.h"
  31. #include "string.h"
  32. //*****************************************************************************
  33. //
  34. //! \addtogroup usblib_host_class
  35. //! @{
  36. //
  37. //*****************************************************************************
  38. //*****************************************************************************
  39. //
  40. // This is the data verify tag passed between requests.
  41. //
  42. //*****************************************************************************
  43. #define CBW_TAG_VALUE 0x54231990
  44. //*****************************************************************************
  45. //
  46. //! This function is used to issue SCSI commands via USB.
  47. //!
  48. //! \param ulInPipe is the USB IN pipe to use for this command.
  49. //! \param ulOutPipe is the USB OUT pipe to use for this command.
  50. //! \param pSCSICmd is the SCSI command structure to send.
  51. //! \param pucData is pointer to the command data to be sent.
  52. //! \param pulSize is the number of bytes is the number of bytes expected or
  53. //! sent by the command.
  54. //!
  55. //! This internal function is used to handle SCSI commands sent by other
  56. //! functions. It serves as a layer between the SCSI command and the USB
  57. //! interface being used to send the command. The \e pSCSI parameter contains
  58. //! the SCSI command to send. For commands that expect data back, the
  59. //! \e pucData is the buffer to store the data into and \e pulSize is used to
  60. //! store the amount of data to request as well as used to indicate how many
  61. //! bytes were filled into the \e pucData buffer on return. For commands that
  62. //! are sending data, \e pucData is the data to be sent and \e pulSize is the
  63. //! number of bytes to send.
  64. //!
  65. //! \return This function returns the SCSI status from the command. The value
  66. //! will be either \b SCSI_CMD_STATUS_PASS or \b SCSI_CMD_STATUS_FAIL.
  67. //
  68. //*****************************************************************************
  69. static unsigned int
  70. USBHSCSISendCommand(unsigned int ulIndex, unsigned int ulInPipe,
  71. unsigned int ulOutPipe, tMSCCBW *pSCSICmd,
  72. unsigned char *pucData, unsigned int *pulSize)
  73. {
  74. tMSCCSW CmdStatus;
  75. unsigned int ulBytes;
  76. memset (&CmdStatus, 0, sizeof(CmdStatus));
  77. //
  78. // Initialize the command status.
  79. //
  80. CmdStatus.dCSWSignature = 0;
  81. CmdStatus.dCSWTag = 0;
  82. CmdStatus.bCSWStatus = SCSI_CMD_STATUS_FAIL;
  83. //
  84. // Set the CBW signature and tag.
  85. //
  86. pSCSICmd->dCBWSignature = CBW_SIGNATURE;
  87. pSCSICmd->dCBWTag = CBW_TAG_VALUE;
  88. //
  89. // Set the size of the data to be returned by the device.
  90. //
  91. pSCSICmd->dCBWDataTransferLength = *pulSize;
  92. //
  93. // Send the command.
  94. //
  95. ulBytes = USBHCDPipeWrite(ulIndex,ulOutPipe,
  96. (unsigned char*)pSCSICmd, sizeof(tMSCCBW));
  97. //
  98. // If no bytes went out then the command failed.
  99. //
  100. if(ulBytes == 0)
  101. {
  102. return(SCSI_CMD_STATUS_FAIL);
  103. }
  104. //
  105. // Only request data if there is data to request.
  106. //
  107. if(pSCSICmd->dCBWDataTransferLength != 0)
  108. {
  109. //
  110. // See if this is a read or a write.
  111. //
  112. if(pSCSICmd->bmCBWFlags & CBWFLAGS_DIR_IN)
  113. {
  114. //
  115. // Read the data back.
  116. //
  117. *pulSize = USBHCDPipeRead(ulIndex, ulInPipe, pucData, *pulSize);
  118. }
  119. else
  120. {
  121. //
  122. // Write the data out.
  123. //
  124. *pulSize = USBHCDPipeWrite(ulIndex, ulOutPipe, pucData, *pulSize);
  125. }
  126. if(0==(*pulSize))
  127. {
  128. return(SCSI_CMD_STATUS_FAIL);
  129. }
  130. }
  131. //
  132. // Get the status of the command.
  133. //
  134. ulBytes = USBHCDPipeRead(ulIndex, ulInPipe, (unsigned char *)&CmdStatus,
  135. sizeof(tMSCCSW));
  136. //
  137. // If the status was invalid or did not have the correct signature then
  138. // indicate a failure.
  139. //
  140. if((ulBytes == 0) || (CmdStatus.dCSWSignature != CSW_SIGNATURE) ||
  141. (CmdStatus.dCSWTag != CBW_TAG_VALUE))
  142. {
  143. return(SCSI_CMD_STATUS_FAIL);
  144. }
  145. //
  146. // Return the status.
  147. //
  148. return((unsigned int)CmdStatus.bCSWStatus);
  149. }
  150. //*****************************************************************************
  151. //
  152. //! This will issue the SCSI inquiry command to a device.
  153. //!
  154. //! \param ulInPipe is the USB IN pipe to use for this command.
  155. //! \param ulOutPipe is the USB OUT pipe to use for this command.
  156. //! \param pucData is the data buffer to return the results into.
  157. //! \param pulSize is the size of buffer that was passed in on entry and the
  158. //! number of bytes returned.
  159. //!
  160. //! This function should be used to issue a SCSI Inquiry command to a mass
  161. //! storage device. To allow for multiple devices, the \e ulInPipe and
  162. //! \e ulOutPipe parameters indicate which USB pipes to use for this call.
  163. //!
  164. //! \note The \e pucData buffer pointer should have at least
  165. //! \b SCSI_INQUIRY_DATA_SZ bytes of data or this function will overflow the
  166. //! buffer.
  167. //!
  168. //! \return This function returns the SCSI status from the command. The value
  169. //! will be either \b SCSI_CMD_STATUS_PASS or \b SCSI_CMD_STATUS_FAIL.
  170. //
  171. //*****************************************************************************
  172. unsigned int
  173. USBHSCSIInquiry(unsigned int ulIndex, unsigned int ulInPipe,
  174. unsigned int ulOutPipe, unsigned char *pucData,
  175. unsigned int *pulSize)
  176. {
  177. tMSCCBW SCSICmd;
  178. memset (&SCSICmd, 0, sizeof(tMSCCBW));
  179. //
  180. // The number of bytes of data that the host expects to transfer on the
  181. // Bulk-In or Bulk-Out endpoint (as indicated by the Direction bit) during
  182. // the execution of this command. If this field is zero, the device and
  183. // the host shall transfer no data between the CBW and the associated CSW,
  184. // and the device shall ignore the value of the Direction bit in
  185. // bmCBWFlags.
  186. //
  187. *pulSize = SCSI_INQUIRY_DATA_SZ;
  188. //
  189. // This is an IN request.
  190. //
  191. SCSICmd.bmCBWFlags = CBWFLAGS_DIR_IN;
  192. //
  193. // Only handle LUN 0.
  194. //
  195. SCSICmd.bCBWLUN = 0;
  196. //
  197. // This is the length of the command itself.
  198. //
  199. SCSICmd.bCBWCBLength = 6;
  200. #if defined (__IAR_SYSTEMS_ICC__)
  201. //
  202. // Send Inquiry command with no request for vital product data.
  203. //
  204. SCSICmd.CBWCB[0] = SCSI_INQUIRY_CMD;
  205. //
  206. // Allocation length.
  207. //
  208. // MSB of Alloc length
  209. //
  210. SCSICmd.CBWCB[3] = (SCSI_INQUIRY_DATA_SZ >> 8 ) & 0xFF;
  211. //
  212. // LSB of alloc length
  213. //
  214. SCSICmd.CBWCB[4] = SCSI_INQUIRY_DATA_SZ & 0xFF;
  215. #elif defined (_TMS320C6X)
  216. //
  217. // Send Inquiry command with no request for vital product data.
  218. //
  219. _mem4(&SCSICmd.CBWCB[0]) = SCSI_INQUIRY_CMD;
  220. //
  221. // Allocation length.
  222. //
  223. _mem4(&SCSICmd.CBWCB[4]) = SCSI_INQUIRY_DATA_SZ;
  224. #else
  225. //
  226. // Send Inquiry command with no request for vital product data.
  227. //
  228. SCSICmd.CBWCB[0] = SCSI_INQUIRY_CMD;
  229. //
  230. // MSB of Alloc length
  231. //
  232. SCSICmd.CBWCB[3] = (SCSI_INQUIRY_DATA_SZ >> 8 ) & 0xFF;
  233. //
  234. // LSB of alloc length
  235. //
  236. SCSICmd.CBWCB[4] = SCSI_INQUIRY_DATA_SZ & 0xFF;
  237. #endif
  238. //
  239. // Send the command and get the results.
  240. //
  241. return(USBHSCSISendCommand(ulIndex, ulInPipe, ulOutPipe, &SCSICmd, pucData,
  242. pulSize));
  243. }
  244. //*****************************************************************************
  245. //
  246. //! This will issue the SCSI read capacity command to a device.
  247. //!
  248. //! \param ulInPipe is the USB IN pipe to use for this command.
  249. //! \param ulOutPipe is the USB OUT pipe to use for this command.
  250. //! \param pucData is the data buffer to return the results into.
  251. //! \param pulSize is the size of buffer that was passed in on entry and the
  252. //! number of bytes returned.
  253. //!
  254. //! This function should be used to issue a SCSI Read Capacity command
  255. //! to a mass storage device that is connected. To allow for multiple devices,
  256. //! the \e ulInPipe and \e ulOutPipe parameters indicate which USB pipes to
  257. //! use for this call.
  258. //!
  259. //! \note The \e pucData buffer pointer should have at least
  260. //! \b SCSI_READ_CAPACITY_SZ bytes of data or this function will overflow the
  261. //! buffer.
  262. //!
  263. //! \return This function returns the SCSI status from the command. The value
  264. //! will be either \b SCSI_CMD_STATUS_PASS or \b SCSI_CMD_STATUS_FAIL.
  265. //
  266. //*****************************************************************************
  267. unsigned int
  268. USBHSCSIReadCapacity(unsigned int ulIndex, unsigned int ulInPipe,
  269. unsigned int ulOutPipe, unsigned char *pucData,
  270. unsigned int *pulSize)
  271. {
  272. tMSCCBW SCSICmd;
  273. memset (&SCSICmd, 0, sizeof(tMSCCBW));
  274. //
  275. // Set the size of the command data.
  276. //
  277. *pulSize = SCSI_READ_CAPACITY_SZ;
  278. //
  279. // This is an IN request.
  280. //
  281. SCSICmd.bmCBWFlags = CBWFLAGS_DIR_IN;
  282. //
  283. // Only handle LUN 0.
  284. //
  285. SCSICmd.bCBWLUN = 0;
  286. //
  287. // Set the length of the command itself.
  288. //
  289. SCSICmd.bCBWCBLength = 12;
  290. //
  291. // Set command to read the capacity
  292. //
  293. #if defined (__IAR_SYSTEMS_ICC__)
  294. SCSICmd.CBWCB[0] = SCSI_READ_CAPACITY;
  295. #elif defined (_TMS320C6X)
  296. _mem4(&SCSICmd.CBWCB[0]) = SCSI_READ_CAPACITY;
  297. #else
  298. SCSICmd.CBWCB[0] = SCSI_READ_CAPACITY;
  299. #endif
  300. //
  301. // Send the command and get the results.
  302. //
  303. return(USBHSCSISendCommand(ulIndex, ulInPipe, ulOutPipe, &SCSICmd, pucData,
  304. pulSize));
  305. }
  306. //*****************************************************************************
  307. //
  308. //! This will issue the SCSI read capacities command to a device.
  309. //!
  310. //! \param ulInPipe is the USB IN pipe to use for this command.
  311. //! \param ulOutPipe is the USB OUT pipe to use for this command.
  312. //! \param pucData is the data buffer to return the results into.
  313. //! \param pulSize is the size of buffer that was passed in on entry and the
  314. //! number of bytes returned.
  315. //!
  316. //! This function should be used to issue a SCSI Read Capacities command
  317. //! to a mass storage device that is connected. To allow for multiple devices,
  318. //! the \e ulInPipe and \e ulOutPipe parameters indicate which USB pipes to
  319. //! use for this call.
  320. //!
  321. //! \return This function returns the SCSI status from the command. The value
  322. //! will be either \b SCSI_CMD_STATUS_PASS or \b SCSI_CMD_STATUS_FAIL.
  323. //
  324. //*****************************************************************************
  325. unsigned int
  326. USBHSCSIReadCapacities(unsigned int ulIndex, unsigned int ulInPipe,
  327. unsigned int ulOutPipe, unsigned char *pucData,
  328. unsigned int *pulSize)
  329. {
  330. tMSCCBW SCSICmd;
  331. memset (&SCSICmd, 0, sizeof(tMSCCBW));
  332. //
  333. // This is an IN request.
  334. //
  335. SCSICmd.bmCBWFlags = CBWFLAGS_DIR_IN;
  336. //
  337. // Only handle LUN 0.
  338. //
  339. SCSICmd.bCBWLUN = 0;
  340. //
  341. // Set the length of the command itself.
  342. //
  343. SCSICmd.bCBWCBLength = 12;
  344. //
  345. // Only use the first byte and set it to the Read Capacity command. The
  346. // rest are set to 0.
  347. //
  348. #if defined (__IAR_SYSTEMS_ICC__)
  349. SCSICmd.CBWCB[0] = SCSI_READ_CAPACITIES;
  350. #elif defined (_TMS320C6X)
  351. _mem4(&SCSICmd.CBWCB[0]) = SCSI_READ_CAPACITIES;
  352. #else
  353. SCSICmd.CBWCB[0] = SCSI_READ_CAPACITIES;
  354. #endif
  355. //
  356. // Send the command and get the results.
  357. //
  358. return(USBHSCSISendCommand(ulIndex, ulInPipe, ulOutPipe, &SCSICmd, pucData,
  359. pulSize));
  360. }
  361. //*****************************************************************************
  362. //
  363. //! This will issue the SCSI Mode Sense(6) command to a device.
  364. //!
  365. //! \param ulInPipe is the USB IN pipe to use for this command.
  366. //! \param ulOutPipe is the USB OUT pipe to use for this command.
  367. //! \param ulFlags is a combination of flags defining the exact query that is
  368. //! to be made.
  369. //! \param pucData is the data buffer to return the results into.
  370. //! \param pulSize is the size of the buffer on entry and number of bytes read
  371. //! on exit.
  372. //!
  373. //! This function should be used to issue a SCSI Mode Sense(6) command
  374. //! to a mass storage device. To allow for multiple devices,the \e ulInPipe
  375. //! and \e ulOutPipe parameters indicate which USB pipes to use for this call.
  376. //! The call will return at most the number of bytes in the \e pulSize
  377. //! parameter, however it can return less and change the \e pulSize parameter
  378. //! to the number of valid bytes in the \e *pulSize buffer.
  379. //!
  380. //! The \e ulFlags parameter is a combination of the following three sets of
  381. //! definitions:
  382. //!
  383. //! One of the following values must be specified:
  384. //!
  385. //! - \b SCSI_MS_PC_CURRENT request for current settings.
  386. //! - \b SCSI_MS_PC_CHANGEABLE request for changeable settings.
  387. //! - \b SCSI_MS_PC_DEFAULT request for default settings.
  388. //! - \b SCSI_MS_PC_SAVED request for the saved values.
  389. //!
  390. //! One of these following values must also be specified to determine the page
  391. //! code for the request:
  392. //!
  393. //! - \b SCSI_MS_PC_VENDOR is the vendor specific page code.
  394. //! - \b SCSI_MS_PC_DISCO is the disconnect/reconnect page code.
  395. //! - \b SCSI_MS_PC_CONTROL is the control page code.
  396. //! - \b SCSI_MS_PC_LUN is the protocol specific LUN page code.
  397. //! - \b SCSI_MS_PC_PORT is the protocol specific port page code.
  398. //! - \b SCSI_MS_PC_POWER is the power condition page code.
  399. //! - \b SCSI_MS_PC_INFORM is the informational exceptions page code.
  400. //! - \b SCSI_MS_PC_ALL will request all pages codes supported by the device.
  401. //!
  402. //! The last value is optional and supports the following global flag:
  403. //! - \b SCSI_MS_DBD disables returning block descriptors.
  404. //!
  405. //! Example: Request for all current settings.
  406. //!
  407. //! \verbatim
  408. //! SCSIModeSense6(ulInPipe, ulOutPipe,
  409. //! SCSI_MS_PC_CURRENT | SCSI_MS_PC_ALL,
  410. //! pucData, pulSize);
  411. //! \endverbatim
  412. //!
  413. //! \return This function returns the SCSI status from the command. The value
  414. //! will be either \b SCSI_CMD_STATUS_PASS or \b SCSI_CMD_STATUS_FAIL.
  415. //
  416. //*****************************************************************************
  417. unsigned int
  418. USBHSCSIModeSense6(unsigned int ulIndex, unsigned int ulInPipe,
  419. unsigned int ulOutPipe, unsigned int ulFlags,
  420. unsigned char *pucData, unsigned int *pulSize)
  421. {
  422. tMSCCBW SCSICmd;
  423. memset (&SCSICmd, 0, sizeof(tMSCCBW));
  424. //
  425. // This is an IN request.
  426. //
  427. SCSICmd.bmCBWFlags = CBWFLAGS_DIR_IN;
  428. //
  429. // Only handle LUN 0.
  430. //
  431. SCSICmd.bCBWLUN = 0;
  432. //
  433. // Set the size of the command data.
  434. //
  435. SCSICmd.bCBWCBLength = 6;
  436. //
  437. // Set the options for the Mode Sense Command (6).
  438. //
  439. #if defined (__IAR_SYSTEMS_ICC__)
  440. SCSICmd.CBWCB[0] = (SCSI_MODE_SENSE_6 | ulFlags);
  441. SCSICmd.CBWCB[1] = 0;
  442. SCSICmd.CBWCB[2] = 0;
  443. SCSICmd.CBWCB[3] = 0;
  444. SCSICmd.CBWCB[4] = (unsigned char)*pulSize;
  445. #elif defined (_TMS320C6X)
  446. _mem4(&SCSICmd.CBWCB[0]) = (SCSI_MODE_SENSE_6 | ulFlags);
  447. _mem4(&SCSICmd.CBWCB[4]) = (unsigned char)*pulSize;
  448. #else
  449. SCSICmd.CBWCB[0] = (SCSI_MODE_SENSE_6 | ulFlags);
  450. SCSICmd.CBWCB[4] = (unsigned char)*pulSize;
  451. #endif
  452. //
  453. // Send the command and get the results.
  454. //
  455. return(USBHSCSISendCommand(ulIndex, ulInPipe, ulOutPipe, &SCSICmd, pucData,
  456. pulSize));
  457. }
  458. //*****************************************************************************
  459. //
  460. //! This function issues a SCSI Test Unit Ready command to a device.
  461. //!
  462. //! \param ulInPipe is the USB IN pipe to use for this command.
  463. //! \param ulOutPipe is the USB OUT pipe to use for this command.
  464. //!
  465. //! This function is used to issue a SCSI Test Unit Ready command to a device.
  466. //! This call will simply return the results of issuing this command.
  467. //!
  468. //! \return This function returns the results of the SCSI Test Unit Ready
  469. //! command. The value will be either \b SCSI_CMD_STATUS_PASS or
  470. //! \b SCSI_CMD_STATUS_FAIL.
  471. //
  472. //*****************************************************************************
  473. unsigned int
  474. USBHSCSITestUnitReady(unsigned int ulIndex, unsigned int ulInPipe,
  475. unsigned int ulOutPipe)
  476. {
  477. tMSCCBW SCSICmd;
  478. unsigned int ulSize;
  479. memset (&SCSICmd, 0, sizeof(tMSCCBW));
  480. //
  481. // No data in this command.
  482. //
  483. ulSize = 0;
  484. //
  485. // This is an IN request.
  486. //
  487. SCSICmd.bmCBWFlags = CBWFLAGS_DIR_IN;
  488. //
  489. // Only handle LUN 0.
  490. //
  491. SCSICmd.bCBWLUN = 0;
  492. //
  493. // Set the size of the command data.
  494. //
  495. SCSICmd.bCBWCBLength = 6;
  496. //
  497. // Set the parameter options.
  498. //
  499. #if defined (__IAR_SYSTEMS_ICC__)
  500. SCSICmd.CBWCB[0] = SCSI_TEST_UNIT_READY;
  501. #elif defined (_TMS320C6X)
  502. _mem4(&SCSICmd.CBWCB[0]) = SCSI_TEST_UNIT_READY;
  503. #else
  504. SCSICmd.CBWCB[0] = SCSI_TEST_UNIT_READY;
  505. #endif
  506. //
  507. // Send the command and get the results.
  508. //
  509. return(USBHSCSISendCommand(ulIndex, ulInPipe, ulOutPipe, &SCSICmd, 0, &ulSize));
  510. }
  511. //*****************************************************************************
  512. //
  513. //! This function issues a SCSI Request Sense command to a device.
  514. //!
  515. //! \param ulInPipe is the USB IN pipe to use for this command.
  516. //! \param ulOutPipe is the USB OUT pipe to use for this command.
  517. //! \param pucData is the data buffer to return the results into.
  518. //! \param pulSize is the size of the buffer on entry and number of bytes read
  519. //! on exit.
  520. //!
  521. //! This function is used to issue a SCSI Request Sense command to a device.
  522. //! It will return the data in the buffer pointed to by \e pucData. The
  523. //! parameter \e pulSize should have the allocation size in bytes of the buffer
  524. //! pointed to by pucData.
  525. //!
  526. //! \return This function returns the results of the SCSI Request Sense
  527. //! command. The value will be either \b SCSI_CMD_STATUS_PASS or
  528. //! \b SCSI_CMD_STATUS_FAIL.
  529. //
  530. //*****************************************************************************
  531. unsigned int
  532. USBHSCSIRequestSense(unsigned int ulIndex, unsigned int ulInPipe,
  533. unsigned int ulOutPipe,
  534. unsigned char *pucData, unsigned int *pulSize)
  535. {
  536. tMSCCBW SCSICmd;
  537. memset (&SCSICmd, 0, sizeof(tMSCCBW));
  538. //
  539. // This is an IN request.
  540. //
  541. SCSICmd.bmCBWFlags = CBWFLAGS_DIR_IN;
  542. //
  543. // Only handle LUN 0.
  544. //
  545. SCSICmd.bCBWLUN = 0;
  546. //
  547. // Set the size of the command data.
  548. //
  549. SCSICmd.bCBWCBLength = 12;
  550. //
  551. // Set the parameter options.
  552. //
  553. #if defined (__IAR_SYSTEMS_ICC__)
  554. SCSICmd.CBWCB[0] = SCSI_REQUEST_SENSE;
  555. SCSICmd.CBWCB[4] = 18;
  556. #elif defined (_TMS320C6X)
  557. _mem4(&SCSICmd.CBWCB[0]) = SCSI_REQUEST_SENSE;
  558. _mem4(&SCSICmd.CBWCB[4]) = 18;
  559. #else
  560. SCSICmd.CBWCB[0] = SCSI_REQUEST_SENSE;
  561. SCSICmd.CBWCB[4] = 18;
  562. #endif
  563. //
  564. // Send the command and get the results.
  565. //
  566. return(USBHSCSISendCommand(ulIndex, ulInPipe, ulOutPipe, &SCSICmd, pucData,
  567. pulSize));
  568. }
  569. //*****************************************************************************
  570. //
  571. //! This function issues a SCSI Read(10) command to a device.
  572. //!
  573. //! \param ulInPipe is the USB IN pipe to use for this command.
  574. //! \param ulOutPipe is the USB OUT pipe to use for this command.
  575. //! \param ulLBA is the logical block address to read.
  576. //! \param pucData is the data buffer to return the data.
  577. //! \param pulSize is the size of the buffer on entry and number of bytes read
  578. //! on exit.
  579. //! \param ulNumBlocks is the number of contiguous blocks to read from the
  580. //! device.
  581. //!
  582. //! This function is used to issue a SCSI Read(10) command to a device. The
  583. //! \e ulLBA parameter specifies the logical block address to read from the
  584. //! device. The data from this block will be returned in the buffer pointed to
  585. //! by \e pucData. The parameter \e pulSize should indicate enough space to
  586. //! hold a full block size, or only the first pulSize bytes of the LBA will
  587. //! be returned.
  588. //!
  589. //! \return This function returns the results of the SCSI Read(10) command.
  590. //! The value will be either \b SCSI_CMD_STATUS_PASS or
  591. //! \b SCSI_CMD_STATUS_FAIL.
  592. //
  593. //*****************************************************************************
  594. unsigned int
  595. USBHSCSIRead10(unsigned int ulIndex, unsigned int ulInPipe,
  596. unsigned int ulOutPipe, unsigned int ulLBA,
  597. unsigned char *pucData, unsigned int *pulSize,
  598. unsigned int ulNumBlocks)
  599. {
  600. tMSCCBW SCSICmd;
  601. memset (&SCSICmd, 0, sizeof(tMSCCBW));
  602. //
  603. // This is an IN request.
  604. //
  605. SCSICmd.bmCBWFlags = CBWFLAGS_DIR_IN;
  606. //
  607. // Only handle LUN 0.
  608. //
  609. SCSICmd.bCBWLUN = 0;
  610. //
  611. // Set the size of the command data.
  612. //
  613. SCSICmd.bCBWCBLength = 10;
  614. //
  615. // Set the parameter options.
  616. //
  617. SCSICmd.CBWCB[0] = SCSI_READ_10;
  618. //
  619. // Clear the reserved field.
  620. //
  621. SCSICmd.CBWCB[1] = 0;
  622. //
  623. // LBA starts at offset 2.
  624. //
  625. SCSICmd.CBWCB[2] = (unsigned char)(ulLBA >> 24);
  626. SCSICmd.CBWCB[3] = (unsigned char)(ulLBA >> 16);
  627. SCSICmd.CBWCB[4] = (unsigned char)(ulLBA >> 8);
  628. SCSICmd.CBWCB[5] = (unsigned char)ulLBA;
  629. //
  630. // Clear the reserved field.
  631. //
  632. SCSICmd.CBWCB[6] = 0;
  633. //
  634. // Transfer length in blocks starts at offset 2.
  635. // This also sets the Control value to 0 at offset 9.
  636. //
  637. SCSICmd.CBWCB[7] = (ulNumBlocks & 0xFF00) >> 8;
  638. #if defined (__IAR_SYSTEMS_ICC__)
  639. SCSICmd.CBWCB[8] = (ulNumBlocks & 0xFF);
  640. #elif defined (_TMS320C6X)
  641. _mem4(&SCSICmd.CBWCB[8]) = (ulNumBlocks & 0xFF);
  642. #else
  643. SCSICmd.CBWCB[8] = (ulNumBlocks & 0xFF);
  644. #endif
  645. //
  646. // Send the command and get the results.
  647. //
  648. return(USBHSCSISendCommand(ulIndex, ulInPipe, ulOutPipe, &SCSICmd, pucData,
  649. pulSize));
  650. }
  651. //*****************************************************************************
  652. //
  653. //! This function issues a SCSI Write(10) command to a device.
  654. //!
  655. //! This function is used to issue a SCSI Write(10) command to a device. The
  656. //! \e ulLBA parameter specifies the logical block address on the device. The
  657. //! data to write to this block should be in the buffer pointed to by
  658. //! \e pucData parameter. The parameter \e pulSize should indicate the amount
  659. //! of data to write to the specified LBA.
  660. //!
  661. //! \param ulInPipe is the USB IN pipe to use for this command.
  662. //! \param ulOutPipe is the USB OUT pipe to use for this command.
  663. //! \param ulLBA is the logical block address to read.
  664. //! \param pucData is the data buffer to write out.
  665. //! \param pulSize is the size of the buffer.
  666. //! \param ulNumBlocks is the number of contiguous blocks to write to the
  667. //! device.
  668. //!
  669. //! \return This function returns the results of the SCSI Write(10) command.
  670. //! The value will be either \b SCSI_CMD_STATUS_PASS or
  671. //! \b SCSI_CMD_STATUS_FAIL.
  672. //
  673. //*****************************************************************************
  674. unsigned int
  675. USBHSCSIWrite10(unsigned int ulIndex, unsigned int ulInPipe,
  676. unsigned int ulOutPipe, unsigned int ulLBA,
  677. unsigned char *pucData, unsigned int *pulSize,
  678. unsigned int ulNumBlocks)
  679. {
  680. tMSCCBW SCSICmd;
  681. memset (&SCSICmd, 0, sizeof(tMSCCBW));
  682. //
  683. // This is an IN request.
  684. //
  685. SCSICmd.bmCBWFlags = CBWFLAGS_DIR_OUT;
  686. //
  687. // Only handle LUN 0.
  688. //
  689. SCSICmd.bCBWLUN = 0;
  690. //
  691. // Set the size of the command data.
  692. //
  693. SCSICmd.bCBWCBLength = 10;
  694. //
  695. // Set the parameter options.
  696. //
  697. SCSICmd.CBWCB[0] = SCSI_WRITE_10;
  698. //
  699. // Clear the reserved field.
  700. //
  701. SCSICmd.CBWCB[1] = 0;
  702. //
  703. // LBA starts at offset 2.
  704. //
  705. SCSICmd.CBWCB[2] = (unsigned char)(ulLBA >> 24);
  706. SCSICmd.CBWCB[3] = (unsigned char)(ulLBA >> 16);
  707. SCSICmd.CBWCB[4] = (unsigned char)(ulLBA >> 8);
  708. SCSICmd.CBWCB[5] = (unsigned char)ulLBA;
  709. //
  710. // Clear the reserved field.
  711. //
  712. SCSICmd.CBWCB[6] = 0;
  713. //
  714. // Set the transfer length in blocks.
  715. // This also sets the Control value to 0 at offset 9.
  716. //
  717. SCSICmd.CBWCB[7] = (ulNumBlocks & 0xFF00) >> 8;
  718. #if defined (__IAR_SYSTEMS_ICC__)
  719. SCSICmd.CBWCB[8] = (ulNumBlocks & 0xFF);
  720. #elif defined (_TMS320C6X)
  721. _mem4(&SCSICmd.CBWCB[8]) = ulNumBlocks & 0xFF;
  722. #else
  723. SCSICmd.CBWCB[8] = (ulNumBlocks & 0xFF);
  724. #endif
  725. //
  726. // Send the command and get the results.
  727. //
  728. return(USBHSCSISendCommand(ulIndex, ulInPipe, ulOutPipe, &SCSICmd, pucData,
  729. pulSize));
  730. }
  731. //*****************************************************************************
  732. //
  733. // Close the Doxygen group.
  734. //! @}
  735. //
  736. //*****************************************************************************