config.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504
  1. // Copyright (C) 2014 Michael McMaster <michael@codesrc.com>
  2. //
  3. // This file is part of SCSI2SD.
  4. //
  5. // SCSI2SD is free software: you can redistribute it and/or modify
  6. // it under the terms of the GNU General Public License as published by
  7. // the Free Software Foundation, either version 3 of the License, or
  8. // (at your option) any later version.
  9. //
  10. // SCSI2SD is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. // GNU General Public License for more details.
  14. //
  15. // You should have received a copy of the GNU General Public License
  16. // along with SCSI2SD. If not, see <http://www.gnu.org/licenses/>.
  17. #include "config.h"
  18. #include "led.h"
  19. #include "bsp.h"
  20. #include "scsi.h"
  21. #include "scsiPhy.h"
  22. #include "sd.h"
  23. #include "disk.h"
  24. #include "bootloader.h"
  25. #include "spinlock.h"
  26. #include "../../include/scsi2sd.h"
  27. #include "../../include/hidpacket.h"
  28. #include "usb_device/usb_device.h"
  29. #include "usb_device/usbd_hid.h"
  30. #include "usb_device/usbd_composite.h"
  31. #include "bsp_driver_sd.h"
  32. #include <string.h>
  33. static const uint16_t FIRMWARE_VERSION = 0x0647;
  34. // Optional static config
  35. extern uint8_t* __fixed_config;
  36. extern SD_HandleTypeDef hsd;
  37. #ifdef S2S_USB_HS
  38. #define configUsbDev hUsbDeviceHS
  39. #else
  40. #define configUsbDev hUsbDeviceFS
  41. #endif
  42. // 1 flash row
  43. static const uint8_t DEFAULT_CONFIG[128] =
  44. {
  45. 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3F, 0x00,
  46. 0x00, 0x02, 0x3F, 0x00, 0xFF, 0x00, 0x20, 0x63, 0x6F, 0x64, 0x65, 0x73,
  47. 0x72, 0x63, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53,
  48. 0x43, 0x53, 0x49, 0x32, 0x53, 0x44, 0x20, 0x31, 0x2E, 0x30, 0x31, 0x32,
  49. 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
  50. 0x37, 0x38, 0x00, 0x00
  51. };
  52. static uint8_t s2s_cfg[S2S_CFG_SIZE] S2S_DMA_ALIGN;
  53. static uint8_t configDmaBuf[512] S2S_DMA_ALIGN; // For SD card writes.
  54. enum USB_STATE
  55. {
  56. USB_IDLE,
  57. USB_DATA_SENT
  58. };
  59. static int usbInEpState;
  60. static void s2s_debugTimer();
  61. // Debug timer to log via USB.
  62. // Timer 6 & 7 is a simple counter with no external IO supported.
  63. static s2s_lock_t usbDevLock = s2s_lock_init;
  64. TIM_HandleTypeDef htim7;
  65. static int debugTimerStarted = 0;
  66. void TIM7_IRQHandler()
  67. {
  68. HAL_TIM_IRQHandler(&htim7);
  69. }
  70. void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
  71. {
  72. if (s2s_spin_trylock(&usbDevLock)) {
  73. s2s_debugTimer();
  74. s2s_spin_unlock(&usbDevLock);
  75. }
  76. }
  77. void s2s_configInit(S2S_BoardCfg* config)
  78. {
  79. usbInEpState = USB_IDLE;
  80. if (memcmp(__fixed_config, "BCFG", 4) == 0)
  81. {
  82. // Use hardcoded config
  83. memcpy(s2s_cfg, __fixed_config, S2S_CFG_SIZE);
  84. memcpy(config, s2s_cfg, sizeof(S2S_BoardCfg));
  85. }
  86. else if ((blockDev.state & DISK_PRESENT) && sdDev.capacity)
  87. {
  88. int cfgSectors = (S2S_CFG_SIZE + 511) / 512;
  89. BSP_SD_ReadBlocks_DMA(
  90. &s2s_cfg[0],
  91. sdDev.capacity - cfgSectors,
  92. cfgSectors);
  93. memcpy(config, s2s_cfg, sizeof(S2S_BoardCfg));
  94. if (memcmp(config->magic, "BCFG", 4))
  95. {
  96. // Invalid SD card config, use default.
  97. memset(&s2s_cfg[0], 0, S2S_CFG_SIZE);
  98. memcpy(config, s2s_cfg, sizeof(S2S_BoardCfg));
  99. memcpy(config->magic, "BCFG", 4);
  100. config->selectionDelay = 255; // auto
  101. config->flags6 = S2S_CFG_ENABLE_TERMINATOR;
  102. memcpy(
  103. &s2s_cfg[0] + sizeof(S2S_BoardCfg),
  104. DEFAULT_CONFIG,
  105. sizeof(S2S_TargetCfg));
  106. }
  107. }
  108. else
  109. {
  110. // No SD card, use existing config if valid
  111. if (memcmp(config->magic, "BCFG", 4))
  112. {
  113. // Not valid, use empty config with no disks.
  114. memset(&s2s_cfg[0], 0, S2S_CFG_SIZE);
  115. memcpy(config, s2s_cfg, sizeof(S2S_BoardCfg));
  116. config->selectionDelay = 255; // auto
  117. config->flags6 = S2S_CFG_ENABLE_TERMINATOR;
  118. }
  119. }
  120. }
  121. static void debugInit(void)
  122. {
  123. if (debugTimerStarted == 1) return;
  124. debugTimerStarted = 1;
  125. // 10ms debug timer to capture logs over USB
  126. __TIM7_CLK_ENABLE();
  127. htim7.Instance = TIM7;
  128. #ifdef STM32F2xx
  129. htim7.Init.Prescaler = 10800 - 1; // 16bit. 108MHz down to 10KHz
  130. #else
  131. htim7.Init.Prescaler = 18000 - 1; // 16bit. 180MHz down to 10KHz
  132. #endif
  133. htim7.Init.CounterMode = TIM_COUNTERMODE_UP;
  134. htim7.Init.Period = 100 - 1; // 16bit. 10KHz down to 10ms.
  135. htim7.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  136. HAL_TIM_Base_Init(&htim7);
  137. HAL_TIM_Base_Start_IT(&htim7);
  138. HAL_NVIC_SetPriority(TIM7_IRQn, 10, 0);
  139. HAL_NVIC_EnableIRQ(TIM7_IRQn);
  140. }
  141. static void
  142. pingCommand()
  143. {
  144. uint8_t response[] =
  145. {
  146. S2S_CFG_STATUS_GOOD
  147. };
  148. hidPacket_send(response, sizeof(response));
  149. }
  150. static void
  151. sdInfoCommand()
  152. {
  153. uint8_t response[sizeof(sdDev.csd) + sizeof(sdDev.cid)];
  154. memcpy(response, sdDev.csd, sizeof(sdDev.csd));
  155. memcpy(response + sizeof(sdDev.csd), sdDev.cid, sizeof(sdDev.cid));
  156. hidPacket_send(response, sizeof(response));
  157. }
  158. static void
  159. scsiTestCommand()
  160. {
  161. int resultCode = scsiSelfTest();
  162. uint8_t response[] =
  163. {
  164. resultCode == 0 ? S2S_CFG_STATUS_GOOD : S2S_CFG_STATUS_ERR,
  165. resultCode
  166. };
  167. hidPacket_send(response, sizeof(response));
  168. }
  169. static void
  170. scsiDevInfoCommand()
  171. {
  172. uint8_t response[] =
  173. {
  174. FIRMWARE_VERSION >> 8,
  175. FIRMWARE_VERSION & 0xff,
  176. sdDev.capacity >> 24,
  177. sdDev.capacity >> 16,
  178. sdDev.capacity >> 8,
  179. sdDev.capacity,
  180. 1 // useSdConfig, always true for V6.
  181. };
  182. hidPacket_send(response, sizeof(response));
  183. }
  184. static void
  185. debugCommand()
  186. {
  187. uint8_t response[32];
  188. memcpy(&response, &scsiDev.cdb, 12);
  189. response[12] = scsiDev.msgIn;
  190. response[13] = scsiDev.msgOut;
  191. response[14] = scsiDev.lastStatus;
  192. response[15] = scsiDev.lastSense;
  193. response[16] = scsiDev.phase;
  194. response[17] = *SCSI_STS_SCSI;
  195. response[18] = scsiDev.target != NULL ? scsiDev.target->syncOffset : 0;
  196. response[19] = scsiDev.target != NULL ? scsiDev.target->syncPeriod : 0;
  197. response[20] = scsiDev.minSyncPeriod;
  198. response[21] = scsiDev.rstCount;
  199. response[22] = scsiDev.selCount;
  200. response[23] = scsiDev.msgCount;
  201. response[24] = scsiDev.cmdCount;
  202. response[25] = scsiDev.watchdogTick;
  203. response[26] = (hsd.State << 4) | blockDev.state;
  204. response[27] = scsiDev.lastSenseASC >> 8;
  205. response[28] = scsiDev.lastSenseASC;
  206. response[29] = *SCSI_STS_DBX & 0xff; // What we've read
  207. response[30] = *SCSI_STS_SELECTED;
  208. response[31] = *SCSI_STS_DBX >> 8; // What we're writing
  209. hidPacket_send(response, sizeof(response));
  210. }
  211. static void
  212. sdWriteCommand(const uint8_t* cmd, size_t cmdSize)
  213. {
  214. if (cmdSize < 517)
  215. {
  216. return; // ignore.
  217. }
  218. uint32_t lba =
  219. (((uint32_t)cmd[1]) << 24) |
  220. (((uint32_t)cmd[2]) << 16) |
  221. (((uint32_t)cmd[3]) << 8) |
  222. ((uint32_t)cmd[4]);
  223. memcpy(configDmaBuf, &cmd[5], 512);
  224. BSP_SD_WriteBlocks_DMA(configDmaBuf, lba, 1);
  225. uint8_t response[] =
  226. {
  227. S2S_CFG_STATUS_GOOD
  228. };
  229. hidPacket_send(response, sizeof(response));
  230. }
  231. static void
  232. sdReadCommand(const uint8_t* cmd, size_t cmdSize)
  233. {
  234. if (cmdSize < 5)
  235. {
  236. return; // ignore.
  237. }
  238. uint32_t lba =
  239. (((uint32_t)cmd[1]) << 24) |
  240. (((uint32_t)cmd[2]) << 16) |
  241. (((uint32_t)cmd[3]) << 8) |
  242. ((uint32_t)cmd[4]);
  243. BSP_SD_ReadBlocks_DMA(configDmaBuf, lba, 1);
  244. hidPacket_send(configDmaBuf, 512);
  245. }
  246. static void
  247. processCommand(const uint8_t* cmd, size_t cmdSize)
  248. {
  249. switch (cmd[0])
  250. {
  251. case S2S_CMD_PING:
  252. pingCommand();
  253. break;
  254. case S2S_CMD_REBOOT:
  255. s2s_enterBootloader();
  256. break;
  257. case S2S_CMD_SDINFO:
  258. sdInfoCommand();
  259. break;
  260. case S2S_CMD_SCSITEST:
  261. scsiTestCommand();
  262. break;
  263. case S2S_CMD_DEVINFO:
  264. scsiDevInfoCommand();
  265. break;
  266. case S2S_CMD_SD_WRITE:
  267. sdWriteCommand(cmd, cmdSize);
  268. break;
  269. case S2S_CMD_SD_READ:
  270. sdReadCommand(cmd, cmdSize);
  271. break;
  272. case S2S_CMD_DEBUG:
  273. if (debugTimerStarted == 0) {
  274. debugInit();
  275. debugCommand();
  276. }
  277. // Always triggered from timer for consistent behaviour
  278. break;
  279. case S2S_CMD_NONE: // invalid
  280. default:
  281. break;
  282. }
  283. }
  284. void s2s_configPoll()
  285. {
  286. s2s_spin_lock(&usbDevLock);
  287. if (!USBD_Composite_IsConfigured(&configUsbDev))
  288. {
  289. usbInEpState = USB_IDLE;
  290. hidPacket_reset();
  291. goto out;
  292. }
  293. if (USBD_HID_IsReportReady(&configUsbDev))
  294. {
  295. // Check if we have a previous command outstanding
  296. // before accepting another
  297. size_t cmdSize;
  298. if (hidPacket_peekPacket(&cmdSize) == NULL)
  299. {
  300. uint8_t hidBuffer[USBHID_LEN];
  301. int byteCount = USBD_HID_GetReport(&configUsbDev, hidBuffer, sizeof(hidBuffer));
  302. hidPacket_recv(hidBuffer, byteCount);
  303. }
  304. }
  305. if (hidPacket_getHIDBytesReady() == 0) // Nothing queued to send
  306. {
  307. size_t cmdSize;
  308. const uint8_t* cmd = hidPacket_peekPacket(&cmdSize);
  309. if (cmd && (cmdSize > 0))
  310. {
  311. if (!debugTimerStarted || (cmd[0] != S2S_CMD_DEBUG))
  312. {
  313. hidPacket_getPacket(&cmdSize);
  314. s2s_ledOn();
  315. processCommand(cmd, cmdSize);
  316. s2s_ledOff();
  317. }
  318. }
  319. }
  320. switch (usbInEpState)
  321. {
  322. case USB_IDLE:
  323. {
  324. uint8_t hidBuffer[USBHID_LEN];
  325. const uint8_t* nextChunk = hidPacket_getHIDBytes(hidBuffer);
  326. if (nextChunk)
  327. {
  328. USBD_HID_SendReport (&configUsbDev, nextChunk, sizeof(hidBuffer));
  329. usbInEpState = USB_DATA_SENT;
  330. }
  331. }
  332. break;
  333. case USB_DATA_SENT:
  334. if (!USBD_HID_IsBusy(&configUsbDev))
  335. {
  336. // Data accepted.
  337. usbInEpState = USB_IDLE;
  338. }
  339. break;
  340. }
  341. out:
  342. s2s_spin_unlock(&usbDevLock);
  343. }
  344. void s2s_debugTimer()
  345. {
  346. if (!USBD_Composite_IsConfigured(&configUsbDev))
  347. {
  348. usbInEpState = USB_IDLE;
  349. hidPacket_reset();
  350. return;
  351. }
  352. if (USBD_HID_IsReportReady(&configUsbDev))
  353. {
  354. // Check if we have a previous command outstanding
  355. // before accepting another
  356. size_t cmdSize;
  357. if (hidPacket_peekPacket(&cmdSize) == NULL)
  358. {
  359. uint8_t hidBuffer[USBHID_LEN];
  360. int byteCount = USBD_HID_GetReport(&configUsbDev, hidBuffer, sizeof(hidBuffer));
  361. hidPacket_recv(hidBuffer, byteCount);
  362. }
  363. }
  364. if (hidPacket_getHIDBytesReady() == 0) // Nothing queued to send
  365. {
  366. size_t cmdSize;
  367. const uint8_t* cmd = hidPacket_peekPacket(&cmdSize);
  368. // This is called from an ISR, only process simple commands.
  369. if (cmd && (cmdSize > 0))
  370. {
  371. if (cmd[0] == S2S_CMD_DEBUG)
  372. {
  373. hidPacket_getPacket(&cmdSize);
  374. debugCommand();
  375. }
  376. else if (cmd[0] == S2S_CMD_PING)
  377. {
  378. hidPacket_getPacket(&cmdSize);
  379. pingCommand();
  380. }
  381. }
  382. }
  383. switch (usbInEpState)
  384. {
  385. case USB_IDLE:
  386. {
  387. uint8_t hidBuffer[USBHID_LEN];
  388. const uint8_t* nextChunk = hidPacket_getHIDBytes(hidBuffer);
  389. if (nextChunk)
  390. {
  391. USBD_HID_SendReport (&configUsbDev, nextChunk, sizeof(hidBuffer));
  392. usbInEpState = USB_DATA_SENT;
  393. }
  394. }
  395. break;
  396. case USB_DATA_SENT:
  397. if (!USBD_HID_IsBusy(&configUsbDev))
  398. {
  399. // Data accepted.
  400. usbInEpState = USB_IDLE;
  401. }
  402. break;
  403. }
  404. }
  405. // Public method for storing MODE SELECT results.
  406. void s2s_configSave(int scsiId, uint16_t bytesPerSector)
  407. {
  408. S2S_TargetCfg* cfg = (S2S_TargetCfg*) s2s_getConfigById(scsiId);
  409. cfg->bytesPerSector = bytesPerSector;
  410. BSP_SD_WriteBlocks_DMA(
  411. &s2s_cfg[0],
  412. sdDev.capacity - S2S_CFG_SIZE,
  413. (S2S_CFG_SIZE + 511) / 512);
  414. }
  415. const S2S_TargetCfg* s2s_getConfigByIndex(int i)
  416. {
  417. return (const S2S_TargetCfg*)
  418. (s2s_cfg + sizeof(S2S_BoardCfg) + (i * sizeof(S2S_TargetCfg)));
  419. }
  420. const S2S_TargetCfg* s2s_getConfigById(int scsiId)
  421. {
  422. int i;
  423. for (i = 0; i < S2S_MAX_TARGETS; ++i)
  424. {
  425. const S2S_TargetCfg* tgt = s2s_getConfigByIndex(i);
  426. if ((tgt->scsiId & S2S_CFG_TARGET_ID_BITS) == scsiId)
  427. {
  428. return tgt;
  429. }
  430. }
  431. return NULL;
  432. }