config.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  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 "scsi.h"
  20. #include "scsiPhy.h"
  21. #include "sd.h"
  22. #include "disk.h"
  23. #include "bootloader.h"
  24. #include "bsp.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 = 0x0627;
  34. // 1 flash row
  35. static const uint8_t DEFAULT_CONFIG[128] =
  36. {
  37. 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3F, 0x00,
  38. 0x00, 0x02, 0x3F, 0x00, 0xFF, 0x00, 0x20, 0x63, 0x6F, 0x64, 0x65, 0x73,
  39. 0x72, 0x63, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53,
  40. 0x43, 0x53, 0x49, 0x32, 0x53, 0x44, 0x20, 0x31, 0x2E, 0x30, 0x31, 0x32,
  41. 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
  42. 0x37, 0x38, 0x00, 0x00
  43. };
  44. static uint8_t s2s_cfg[S2S_CFG_SIZE] S2S_DMA_ALIGN;
  45. static uint8_t configDmaBuf[512] S2S_DMA_ALIGN; // For SD card writes.
  46. enum USB_STATE
  47. {
  48. USB_IDLE,
  49. USB_DATA_SENT
  50. };
  51. static int usbInEpState;
  52. static void s2s_debugTimer();
  53. // Debug timer to log via USB.
  54. // Timer 6 & 7 is a simple counter with no external IO supported.
  55. static s2s_lock_t usbDevLock = s2s_lock_init;
  56. TIM_HandleTypeDef htim7;
  57. static int debugTimerStarted = 0;
  58. void TIM7_IRQHandler()
  59. {
  60. HAL_TIM_IRQHandler(&htim7);
  61. }
  62. void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
  63. {
  64. if (s2s_spin_trylock(&usbDevLock)) {
  65. s2s_debugTimer();
  66. s2s_spin_unlock(&usbDevLock);
  67. }
  68. }
  69. void s2s_configInit(S2S_BoardCfg* config)
  70. {
  71. usbInEpState = USB_IDLE;
  72. if ((blockDev.state & DISK_PRESENT) && sdDev.capacity)
  73. {
  74. int cfgSectors = (S2S_CFG_SIZE + 511) / 512;
  75. BSP_SD_ReadBlocks_DMA(
  76. (uint32_t*) &s2s_cfg[0],
  77. (sdDev.capacity - cfgSectors) * 512ll,
  78. 512,
  79. cfgSectors);
  80. memcpy(config, s2s_cfg, sizeof(S2S_BoardCfg));
  81. if (memcmp(config->magic, "BCFG", 4))
  82. {
  83. // Invalid SD card config, use default.
  84. memset(&s2s_cfg[0], 0, S2S_CFG_SIZE);
  85. memcpy(config, s2s_cfg, sizeof(S2S_BoardCfg));
  86. memcpy(config->magic, "BCFG", 4);
  87. config->selectionDelay = 255; // auto
  88. config->flags6 = S2S_CFG_ENABLE_TERMINATOR;
  89. memcpy(
  90. &s2s_cfg[0] + sizeof(S2S_BoardCfg),
  91. DEFAULT_CONFIG,
  92. sizeof(S2S_TargetCfg));
  93. }
  94. }
  95. else
  96. {
  97. // No SD card, use existing config if valid
  98. if (memcmp(config->magic, "BCFG", 4))
  99. {
  100. // Not valid, use empty config with no disks.
  101. memset(&s2s_cfg[0], 0, S2S_CFG_SIZE);
  102. memcpy(config, s2s_cfg, sizeof(S2S_BoardCfg));
  103. config->selectionDelay = 255; // auto
  104. config->flags6 = S2S_CFG_ENABLE_TERMINATOR;
  105. }
  106. }
  107. }
  108. static void debugInit(void)
  109. {
  110. if (debugTimerStarted == 1) return;
  111. debugTimerStarted = 1;
  112. // 10ms debug timer to capture logs over USB
  113. __TIM7_CLK_ENABLE();
  114. htim7.Instance = TIM7;
  115. htim7.Init.Prescaler = 10800 - 1; // 16bit. 108MHz down to 10KHz
  116. htim7.Init.CounterMode = TIM_COUNTERMODE_UP;
  117. htim7.Init.Period = 100 - 1; // 16bit. 10KHz down to 10ms.
  118. htim7.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  119. HAL_TIM_Base_Init(&htim7);
  120. HAL_TIM_Base_Start_IT(&htim7);
  121. HAL_NVIC_SetPriority(TIM7_IRQn, 10, 0);
  122. HAL_NVIC_EnableIRQ(TIM7_IRQn);
  123. }
  124. static void
  125. pingCommand()
  126. {
  127. uint8_t response[] =
  128. {
  129. S2S_CFG_STATUS_GOOD
  130. };
  131. hidPacket_send(response, sizeof(response));
  132. }
  133. static void
  134. sdInfoCommand()
  135. {
  136. uint8_t response[sizeof(sdDev.csd) + sizeof(sdDev.cid)];
  137. memcpy(response, sdDev.csd, sizeof(sdDev.csd));
  138. memcpy(response + sizeof(sdDev.csd), sdDev.cid, sizeof(sdDev.cid));
  139. hidPacket_send(response, sizeof(response));
  140. }
  141. static void
  142. scsiTestCommand()
  143. {
  144. int resultCode = scsiSelfTest();
  145. uint8_t response[] =
  146. {
  147. resultCode == 0 ? S2S_CFG_STATUS_GOOD : S2S_CFG_STATUS_ERR,
  148. resultCode
  149. };
  150. hidPacket_send(response, sizeof(response));
  151. }
  152. static void
  153. scsiDevInfoCommand()
  154. {
  155. uint8_t response[] =
  156. {
  157. FIRMWARE_VERSION >> 8,
  158. FIRMWARE_VERSION & 0xff,
  159. sdDev.capacity >> 24,
  160. sdDev.capacity >> 16,
  161. sdDev.capacity >> 8,
  162. sdDev.capacity,
  163. 1 // useSdConfig, always true for V6.
  164. };
  165. hidPacket_send(response, sizeof(response));
  166. }
  167. static void
  168. debugCommand()
  169. {
  170. uint8_t response[32];
  171. memcpy(&response, &scsiDev.cdb, 12);
  172. response[12] = scsiDev.msgIn;
  173. response[13] = scsiDev.msgOut;
  174. response[14] = scsiDev.lastStatus;
  175. response[15] = scsiDev.lastSense;
  176. response[16] = scsiDev.phase;
  177. response[17] = *SCSI_STS_SCSI;
  178. response[18] = scsiDev.target != NULL ? scsiDev.target->syncOffset : 0;
  179. response[19] = scsiDev.target != NULL ? scsiDev.target->syncPeriod : 0;
  180. response[20] = scsiDev.minSyncPeriod;
  181. response[21] = scsiDev.rstCount;
  182. response[22] = scsiDev.selCount;
  183. response[23] = scsiDev.msgCount;
  184. response[24] = scsiDev.cmdCount;
  185. response[25] = scsiDev.watchdogTick;
  186. response[26] = blockDev.state;
  187. response[27] = scsiDev.lastSenseASC >> 8;
  188. response[28] = scsiDev.lastSenseASC;
  189. response[29] = *SCSI_STS_DBX & 0xff; // What we've read
  190. response[30] = *SCSI_STS_SELECTED;
  191. response[31] = *SCSI_STS_DBX >> 8; // What we're writing
  192. hidPacket_send(response, sizeof(response));
  193. }
  194. static void
  195. sdWriteCommand(const uint8_t* cmd, size_t cmdSize)
  196. {
  197. if (cmdSize < 517)
  198. {
  199. return; // ignore.
  200. }
  201. uint32_t lba =
  202. (((uint32_t)cmd[1]) << 24) |
  203. (((uint32_t)cmd[2]) << 16) |
  204. (((uint32_t)cmd[3]) << 8) |
  205. ((uint32_t)cmd[4]);
  206. memcpy(configDmaBuf, &cmd[5], 512);
  207. BSP_SD_WriteBlocks_DMA((uint32_t*) configDmaBuf, lba * 512ll, 512, 1);
  208. uint8_t response[] =
  209. {
  210. S2S_CFG_STATUS_GOOD
  211. };
  212. hidPacket_send(response, sizeof(response));
  213. }
  214. static void
  215. sdReadCommand(const uint8_t* cmd, size_t cmdSize)
  216. {
  217. if (cmdSize < 5)
  218. {
  219. return; // ignore.
  220. }
  221. uint32_t lba =
  222. (((uint32_t)cmd[1]) << 24) |
  223. (((uint32_t)cmd[2]) << 16) |
  224. (((uint32_t)cmd[3]) << 8) |
  225. ((uint32_t)cmd[4]);
  226. BSP_SD_ReadBlocks_DMA((uint32_t*) configDmaBuf, lba * 512ll, 512, 1);
  227. hidPacket_send(configDmaBuf, 512);
  228. }
  229. static void
  230. processCommand(const uint8_t* cmd, size_t cmdSize)
  231. {
  232. switch (cmd[0])
  233. {
  234. case S2S_CMD_PING:
  235. pingCommand();
  236. break;
  237. case S2S_CMD_REBOOT:
  238. s2s_enterBootloader();
  239. break;
  240. case S2S_CMD_SDINFO:
  241. sdInfoCommand();
  242. break;
  243. case S2S_CMD_SCSITEST:
  244. scsiTestCommand();
  245. break;
  246. case S2S_CMD_DEVINFO:
  247. scsiDevInfoCommand();
  248. break;
  249. case S2S_CMD_SD_WRITE:
  250. sdWriteCommand(cmd, cmdSize);
  251. break;
  252. case S2S_CMD_SD_READ:
  253. sdReadCommand(cmd, cmdSize);
  254. break;
  255. case S2S_CMD_DEBUG:
  256. if (debugTimerStarted == 0) {
  257. debugInit();
  258. }
  259. debugCommand();
  260. break;
  261. case S2S_CMD_NONE: // invalid
  262. default:
  263. break;
  264. }
  265. }
  266. void s2s_configPoll()
  267. {
  268. s2s_spin_lock(&usbDevLock);
  269. if (!USBD_Composite_IsConfigured(&hUsbDeviceFS))
  270. {
  271. usbInEpState = USB_IDLE;
  272. goto out;
  273. }
  274. if (USBD_HID_IsReportReady(&hUsbDeviceFS))
  275. {
  276. s2s_ledOn();
  277. // The host sent us some data!
  278. uint8_t hidBuffer[USBHID_LEN];
  279. int byteCount = USBD_HID_GetReport(&hUsbDeviceFS, hidBuffer, sizeof(hidBuffer));
  280. hidPacket_recv(hidBuffer, byteCount);
  281. size_t cmdSize;
  282. const uint8_t* cmd = hidPacket_getPacket(&cmdSize);
  283. if (cmd && (cmdSize > 0))
  284. {
  285. processCommand(cmd, cmdSize);
  286. }
  287. s2s_ledOff();
  288. }
  289. switch (usbInEpState)
  290. {
  291. case USB_IDLE:
  292. {
  293. uint8_t hidBuffer[USBHID_LEN];
  294. const uint8_t* nextChunk = hidPacket_getHIDBytes(hidBuffer);
  295. if (nextChunk)
  296. {
  297. USBD_HID_SendReport (&hUsbDeviceFS, nextChunk, sizeof(hidBuffer));
  298. usbInEpState = USB_DATA_SENT;
  299. }
  300. }
  301. break;
  302. case USB_DATA_SENT:
  303. if (!USBD_HID_IsBusy(&hUsbDeviceFS))
  304. {
  305. // Data accepted.
  306. usbInEpState = USB_IDLE;
  307. }
  308. break;
  309. }
  310. out:
  311. s2s_spin_unlock(&usbDevLock);
  312. }
  313. void s2s_debugTimer()
  314. {
  315. if (!USBD_Composite_IsConfigured(&hUsbDeviceFS))
  316. {
  317. usbInEpState = USB_IDLE;
  318. return;
  319. }
  320. if (USBD_HID_IsReportReady(&hUsbDeviceFS))
  321. {
  322. uint8_t hidBuffer[USBHID_LEN];
  323. int byteCount = USBD_HID_GetReport(&hUsbDeviceFS, hidBuffer, sizeof(hidBuffer));
  324. hidPacket_recv(hidBuffer, byteCount);
  325. size_t cmdSize;
  326. const uint8_t* cmd = hidPacket_peekPacket(&cmdSize);
  327. // This is called from an ISR, only process simple commands.
  328. if (cmd && (cmdSize > 0))
  329. {
  330. if (cmd[0] == S2S_CMD_DEBUG)
  331. {
  332. hidPacket_getPacket(&cmdSize);
  333. debugCommand();
  334. }
  335. else if (cmd[0] == S2S_CMD_PING)
  336. {
  337. hidPacket_getPacket(&cmdSize);
  338. pingCommand();
  339. }
  340. }
  341. }
  342. switch (usbInEpState)
  343. {
  344. case USB_IDLE:
  345. {
  346. uint8_t hidBuffer[USBHID_LEN];
  347. const uint8_t* nextChunk = hidPacket_getHIDBytes(hidBuffer);
  348. if (nextChunk)
  349. {
  350. USBD_HID_SendReport (&hUsbDeviceFS, nextChunk, sizeof(hidBuffer));
  351. usbInEpState = USB_DATA_SENT;
  352. }
  353. }
  354. break;
  355. case USB_DATA_SENT:
  356. if (!USBD_HID_IsBusy(&hUsbDeviceFS))
  357. {
  358. // Data accepted.
  359. usbInEpState = USB_IDLE;
  360. }
  361. break;
  362. }
  363. }
  364. // Public method for storing MODE SELECT results.
  365. void s2s_configSave(int scsiId, uint16_t bytesPerSector)
  366. {
  367. S2S_TargetCfg* cfg = (S2S_TargetCfg*) s2s_getConfigById(scsiId);
  368. cfg->bytesPerSector = bytesPerSector;
  369. BSP_SD_WriteBlocks_DMA(
  370. (uint32_t*) &s2s_cfg[0],
  371. (sdDev.capacity - S2S_CFG_SIZE) * 512ll,
  372. 512,
  373. (S2S_CFG_SIZE + 511) / 512);
  374. }
  375. const S2S_TargetCfg* s2s_getConfigByIndex(int i)
  376. {
  377. return (const S2S_TargetCfg*)
  378. (s2s_cfg + sizeof(S2S_BoardCfg) + (i * sizeof(S2S_TargetCfg)));
  379. }
  380. const S2S_TargetCfg* s2s_getConfigById(int scsiId)
  381. {
  382. int i;
  383. for (i = 0; i < S2S_MAX_TARGETS; ++i)
  384. {
  385. const S2S_TargetCfg* tgt = s2s_getConfigByIndex(i);
  386. if ((tgt->scsiId & S2S_CFG_TARGET_ID_BITS) == scsiId)
  387. {
  388. return tgt;
  389. }
  390. }
  391. return NULL;
  392. }