BlueSCSI_settings.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609
  1. /**
  2. * This file is originally part of ZuluSCSI adopted for BlueSCSI
  3. *
  4. * ZuluSCSI™ - Copyright (c) 2023-2025 Rabbit Hole Computing™
  5. * Copyright (c) 2023-2025 Eric Helgeson
  6. *
  7. * This file is licensed under the GPL version 3 or any later version.  
  8. *
  9. * https://www.gnu.org/licenses/gpl-3.0.html
  10. * ----
  11. * This program is free software: you can redistribute it and/or modify
  12. * it under the terms of the GNU General Public License as published by
  13. * the Free Software Foundation, either version 3 of the License, or
  14. * (at your option) any later version. 
  15. *
  16. * This program is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19. * GNU General Public License for more details. 
  20. *
  21. * You should have received a copy of the GNU General Public License
  22. * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  23. **/
  24. #include "BlueSCSI_disk.h"
  25. #include "BlueSCSI_audio.h"
  26. #include "BlueSCSI_log.h"
  27. #include "BlueSCSI_config.h"
  28. #include "BlueSCSI_settings.h"
  29. #include "BlueSCSI_platform.h"
  30. #include <strings.h>
  31. #include <minIni.h>
  32. #include <minIni_cache.h>
  33. // SCSI system and device settings
  34. BlueSCSISettings g_scsi_settings;
  35. const char *systemPresetName[] = {"", "Mac", "MacPlus", "MPC3000", "MegaSTE", "X68000", "X68000-SCSI", "X68000-SASI", "NeXT", "Generic"};
  36. const char *devicePresetName[] = {"", "ST32430N"};
  37. // must be in the same order as bluescsi_speed_grade_t in BlueSCSI_settings.h
  38. const char * const speed_grade_strings[] =
  39. {
  40. "Default",
  41. "TurboMax",
  42. "Custom",
  43. "AudioSPDIF",
  44. "AudioI2S",
  45. "A",
  46. "B",
  47. "C",
  48. "WifiRM2"
  49. };
  50. // Helper function for case-insensitive string compare
  51. static bool strequals(const char *a, const char *b)
  52. {
  53. return strcasecmp(a, b) == 0;
  54. }
  55. // Verify format conformance to SCSI spec:
  56. // - Empty bytes filled with 0x20 (space)
  57. // - Only values 0x20 to 0x7E
  58. // - Left alignment for vendor/product/revision, right alignment for serial.
  59. static void formatDriveInfoField(char *field, int fieldsize, bool align_right)
  60. {
  61. if (align_right)
  62. {
  63. // Right align and trim spaces on either side
  64. int dst = fieldsize - 1;
  65. for (int src = fieldsize - 1; src >= 0; src--)
  66. {
  67. char c = field[src];
  68. if (c < 0x20 || c > 0x7E) c = 0x20;
  69. if (c != 0x20 || dst != fieldsize - 1)
  70. {
  71. field[dst--] = c;
  72. }
  73. }
  74. while (dst >= 0)
  75. {
  76. field[dst--] = 0x20;
  77. }
  78. }
  79. else
  80. {
  81. // Left align, preserve spaces in case config tries to manually right-align
  82. int dst = 0;
  83. for (int src = 0; src < fieldsize; src++)
  84. {
  85. char c = field[src];
  86. if (c < 0x20 || c > 0x7E) c = 0x20;
  87. field[dst++] = c;
  88. }
  89. while (dst < fieldsize)
  90. {
  91. field[dst++] = 0x20;
  92. }
  93. }
  94. }
  95. const char **BlueSCSISettings::deviceInitST32430N(uint8_t scsiId)
  96. {
  97. static const char *st32430n[4] = {"SEAGATE", devicePresetName[DEV_PRESET_ST32430N], PLATFORM_REVISION, ""};
  98. m_dev[scsiId].deviceType = S2S_CFG_FIXED;
  99. m_dev[scsiId].sectorSDBegin = 0;
  100. m_dev[scsiId].sectorSDEnd = 4397055; // 2147MB into bytes and divide 512 - 1
  101. m_devPreset[scsiId] = DEV_PRESET_ST32430N;
  102. return st32430n;
  103. }
  104. void BlueSCSISettings::setDefaultDriveInfo(uint8_t scsiId, const char *presetName, S2S_CFG_TYPE type)
  105. {
  106. char section[6] = "SCSI0";
  107. section[4] += scsiId;
  108. scsi_device_settings_t &cfgDev = m_dev[scsiId];
  109. scsi_device_settings_t &cfgDefault = m_dev[SCSI_SETTINGS_SYS_IDX];
  110. static const char * const driveinfo_fixed[4] = DRIVEINFO_FIXED;
  111. static const char * const driveinfo_removable[4] = DRIVEINFO_REMOVABLE;
  112. static const char * const driveinfo_optical[4] = DRIVEINFO_OPTICAL;
  113. static const char * const driveinfo_floppy[4] = DRIVEINFO_FLOPPY;
  114. static const char * const driveinfo_magopt[4] = DRIVEINFO_MAGOPT;
  115. static const char * const driveinfo_network[4] = DRIVEINFO_NETWORK;
  116. static const char * const driveinfo_tape[4] = DRIVEINFO_TAPE;
  117. static const char * const apl_driveinfo_fixed[4] = APPLE_DRIVEINFO_FIXED;
  118. static const char * const apl_driveinfo_removable[4] = APPLE_DRIVEINFO_REMOVABLE;
  119. static const char * const apl_driveinfo_optical[4] = APPLE_DRIVEINFO_OPTICAL;
  120. static const char * const apl_driveinfo_floppy[4] = APPLE_DRIVEINFO_FLOPPY;
  121. static const char * const apl_driveinfo_magopt[4] = APPLE_DRIVEINFO_MAGOPT;
  122. static const char * const apl_driveinfo_network[4] = APPLE_DRIVEINFO_NETWORK;
  123. static const char * const apl_driveinfo_tape[4] = APPLE_DRIVEINFO_TAPE;
  124. static const char * const iomega_driveinfo_removeable[4] = IOMEGA_DRIVEINFO_ZIP100;
  125. const char * const * driveinfo = NULL;
  126. bool known_preset = false;
  127. scsi_system_settings_t& cfgSys = m_sys;
  128. #ifdef BLUESCSI_HARDWARE_CONFIG
  129. if (g_hw_config.is_active() && g_hw_config.device_preset() == DEV_PRESET_NONE)
  130. {
  131. // empty preset, use default
  132. known_preset = true;
  133. m_devPreset[scsiId] = DEV_PRESET_NONE;
  134. }
  135. else if (g_hw_config.is_active() && g_hw_config.device_preset() == DEV_PRESET_ST32430N)
  136. {
  137. driveinfo = deviceInitST32430N(scsiId);
  138. m_devPreset[scsiId] = DEV_PRESET_ST32430N;
  139. known_preset = true;
  140. }
  141. else
  142. #endif //BLUESCSI_HARDWARE_CONFIG
  143. if (strequals(devicePresetName[DEV_PRESET_NONE], presetName))
  144. {
  145. // empty preset, use default
  146. known_preset = true;
  147. m_devPreset[scsiId] = DEV_PRESET_NONE;
  148. }
  149. else if (strequals(devicePresetName[DEV_PRESET_ST32430N], presetName))
  150. {
  151. driveinfo = deviceInitST32430N(scsiId);
  152. known_preset = true;
  153. }
  154. if (!known_preset)
  155. {
  156. m_devPreset[scsiId] = DEV_PRESET_NONE;
  157. logmsg("Unknown Device preset name ", presetName, ", using default settings");
  158. }
  159. if (m_devPreset[scsiId] == DEV_PRESET_NONE)
  160. {
  161. cfgDev.deviceType = type;
  162. cfgDev.deviceType = ini_getl(section, "Type", cfgDev.deviceType, CONFIGFILE);
  163. if (cfgSys.quirks == S2S_CFG_QUIRKS_APPLE)
  164. {
  165. // Use default drive IDs that are recognized by Apple machines
  166. switch (cfgDev.deviceType)
  167. {
  168. case S2S_CFG_FIXED: driveinfo = apl_driveinfo_fixed; break;
  169. case S2S_CFG_REMOVABLE: driveinfo = apl_driveinfo_removable; break;
  170. case S2S_CFG_OPTICAL: driveinfo = apl_driveinfo_optical; break;
  171. case S2S_CFG_FLOPPY_14MB: driveinfo = apl_driveinfo_floppy; break;
  172. case S2S_CFG_MO: driveinfo = apl_driveinfo_magopt; break;
  173. case S2S_CFG_NETWORK: driveinfo = apl_driveinfo_network; break;
  174. case S2S_CFG_SEQUENTIAL: driveinfo = apl_driveinfo_tape; break;
  175. case S2S_CFG_ZIP100: driveinfo = iomega_driveinfo_removeable; break;
  176. default: driveinfo = apl_driveinfo_fixed; break;
  177. }
  178. }
  179. else
  180. {
  181. // Generic IDs
  182. switch (cfgDev.deviceType)
  183. {
  184. case S2S_CFG_FIXED: driveinfo = driveinfo_fixed; break;
  185. case S2S_CFG_REMOVABLE: driveinfo = driveinfo_removable; break;
  186. case S2S_CFG_OPTICAL: driveinfo = driveinfo_optical; break;
  187. case S2S_CFG_FLOPPY_14MB: driveinfo = driveinfo_floppy; break;
  188. case S2S_CFG_MO: driveinfo = driveinfo_magopt; break;
  189. case S2S_CFG_NETWORK: driveinfo = driveinfo_network; break;
  190. case S2S_CFG_SEQUENTIAL: driveinfo = driveinfo_tape; break;
  191. case S2S_CFG_ZIP100: driveinfo = iomega_driveinfo_removeable; break;
  192. default: driveinfo = driveinfo_fixed; break;
  193. }
  194. }
  195. }
  196. // If the scsi string has not been set system wide use default scsi string
  197. if (!cfgDefault.vendor[0] && driveinfo[0][0])
  198. strncpy(cfgDev.vendor, driveinfo[0], sizeof(cfgDev.vendor));
  199. if (!cfgDefault.prodId[0] && driveinfo[1][0])
  200. strncpy(cfgDev.prodId, driveinfo[1], sizeof(cfgDev.prodId));
  201. if (!cfgDefault.revision[0] && driveinfo[2][0])
  202. strncpy(cfgDev.revision, driveinfo[2], sizeof(cfgDev.revision));
  203. if (!cfgDefault.serial[0] && driveinfo[3][0])
  204. strncpy(cfgDev.serial, driveinfo[3], sizeof(cfgDev.serial));
  205. }
  206. // Read device settings
  207. static void readIniSCSIDeviceSetting(scsi_device_settings_t &cfg, const char *section)
  208. {
  209. cfg.deviceTypeModifier = ini_getl(section, "TypeModifier", cfg.deviceTypeModifier, CONFIGFILE);
  210. cfg.sectorsPerTrack = ini_getl(section, "SectorsPerTrack", cfg.sectorsPerTrack, CONFIGFILE);
  211. cfg.headsPerCylinder = ini_getl(section, "HeadsPerCylinder", cfg.headsPerCylinder, CONFIGFILE);
  212. cfg.prefetchBytes = ini_getl(section, "PrefetchBytes", cfg.prefetchBytes, CONFIGFILE);
  213. cfg.ejectButton = ini_getl(section, "EjectButton", cfg.ejectButton, CONFIGFILE);
  214. cfg.ejectBlinkTimes = ini_getl(section, "EjectBlinkTimes", cfg.ejectBlinkTimes, CONFIGFILE);
  215. cfg.ejectBlinkPeriod = ini_getl(section, "EjectBlinkPeriod", cfg.ejectBlinkPeriod, CONFIGFILE);
  216. cfg.vol = ini_getl(section, "CDAVolume", cfg.vol, CONFIGFILE) & 0xFF;
  217. cfg.nameFromImage = ini_getbool(section, "NameFromImage", cfg.nameFromImage, CONFIGFILE);
  218. cfg.rightAlignStrings = ini_getbool(section, "RightAlignStrings", cfg.rightAlignStrings , CONFIGFILE);
  219. cfg.reinsertOnInquiry = ini_getbool(section, "ReinsertCDOnInquiry", cfg.reinsertOnInquiry, CONFIGFILE);
  220. cfg.reinsertAfterEject = ini_getbool(section, "ReinsertAfterEject", cfg.reinsertAfterEject, CONFIGFILE);
  221. cfg.startEjected = ini_getbool(section, "StartEjected", cfg.startEjected, CONFIGFILE);
  222. cfg.disableMacSanityCheck = ini_getbool(section, "DisableMacSanityCheck", cfg.disableMacSanityCheck, CONFIGFILE);
  223. cfg.sectorSDBegin = ini_getl(section, "SectorSDBegin", cfg.sectorSDBegin, CONFIGFILE);
  224. cfg.sectorSDEnd = ini_getl(section, "SectorSDEnd", cfg.sectorSDEnd, CONFIGFILE);
  225. cfg.vendorExtensions = ini_getl(section, "VendorExtensions", cfg.vendorExtensions, CONFIGFILE);
  226. cfg.blockSize = ini_getl(section, "BlockSize", cfg.blockSize, CONFIGFILE);
  227. char tmp[32];
  228. ini_gets(section, "Vendor", "", tmp, sizeof(tmp), CONFIGFILE);
  229. if (tmp[0])
  230. {
  231. memset(cfg.vendor, 0, sizeof(cfg.vendor));
  232. strncpy(cfg.vendor, tmp, sizeof(cfg.vendor));
  233. }
  234. memset(tmp, 0, sizeof(tmp));
  235. ini_gets(section, "Product", "", tmp, sizeof(tmp), CONFIGFILE);
  236. if (tmp[0])
  237. {
  238. memset(cfg.prodId, 0, sizeof(cfg.prodId));
  239. strncpy(cfg.prodId, tmp, sizeof(cfg.prodId));
  240. }
  241. memset(tmp, 0, sizeof(tmp));
  242. ini_gets(section, "Version", "", tmp, sizeof(tmp), CONFIGFILE);
  243. if (tmp[0])
  244. {
  245. memset(cfg.revision, 0, sizeof(cfg.revision));
  246. strncpy(cfg.revision, tmp, sizeof(cfg.revision));
  247. }
  248. memset(tmp, 0, sizeof(tmp));
  249. ini_gets(section, "Serial", "", tmp, sizeof(tmp), CONFIGFILE);
  250. if (tmp[0])
  251. {
  252. memset(cfg.serial, 0, sizeof(cfg.serial));
  253. strncpy(cfg.serial, tmp, sizeof(cfg.serial));
  254. }
  255. }
  256. scsi_system_settings_t *BlueSCSISettings::initSystem(const char *presetName)
  257. {
  258. scsi_system_settings_t &cfgSys = m_sys;
  259. scsi_device_settings_t &cfgDev = m_dev[SCSI_SETTINGS_SYS_IDX];
  260. // This is a hack to figure out if apple quirks is on via a dip switch
  261. S2S_TargetCfg img;
  262. img.quirks = S2S_CFG_QUIRKS_APPLE;
  263. #ifdef PLATFORM_CONFIG_HOOK
  264. PLATFORM_CONFIG_HOOK(&img);
  265. #endif
  266. // Default settings for host compatibility
  267. cfgSys.quirks = img.quirks;
  268. cfgSys.selectionDelay = 255;
  269. cfgSys.maxSyncSpeed = PLATFORM_DEFAULT_SCSI_SPEED_SETTING;
  270. cfgSys.initPreDelay = 0;
  271. cfgSys.initPostDelay = 0;
  272. cfgSys.phyMode = 0;
  273. cfgSys.enableUnitAttention = false;
  274. cfgSys.enableSCSI2 = true;
  275. cfgSys.enableSelLatch = false;
  276. cfgSys.mapLunsToIDs = false;
  277. cfgSys.enableParity = true;
  278. cfgSys.useFATAllocSize = false;
  279. cfgSys.enableCDAudio = false;
  280. cfgSys.maxVolume = 100;
  281. cfgSys.enableUSBMassStorage = true;
  282. cfgSys.usbMassStorageWaitPeriod = 1000;
  283. cfgSys.usbMassStoragePresentImages = false;
  284. cfgSys.invertStatusLed = false;
  285. #if defined(BLUESCSI_MCU_RP23XX) || defined(BLUESCSI_MCU_RP20XX)
  286. cfgSys.speedGrade = bluescsi_speed_grade_t::SPEED_GRADE_200MHZ;
  287. #else
  288. cfgSys.speedGrade = bluescsi_speed_grade_t::SPEED_GRADE_DEFAULT;
  289. #endif
  290. // setting set for all or specific devices
  291. cfgDev.deviceType = S2S_CFG_NOT_SET;
  292. cfgDev.deviceTypeModifier = 0;
  293. cfgDev.sectorsPerTrack = 0;
  294. cfgDev.headsPerCylinder = 0;
  295. cfgDev.prefetchBytes = PREFETCH_BUFFER_SIZE;
  296. cfgDev.ejectButton = 0;
  297. cfgDev.ejectBlinkTimes = 20;
  298. cfgDev.ejectBlinkPeriod = 50;
  299. cfgDev.vol = DEFAULT_VOLUME_LEVEL;
  300. cfgDev.nameFromImage = false;
  301. cfgDev.rightAlignStrings = false;
  302. cfgDev.reinsertOnInquiry = true;
  303. cfgDev.reinsertAfterEject = true;
  304. cfgDev.startEjected = false; // if true, reinsert after eject and reinsert on inquiry will be set to false.
  305. cfgDev.disableMacSanityCheck = false;
  306. cfgDev.sectorSDBegin = 0;
  307. cfgDev.sectorSDEnd = 0;
  308. cfgDev.vendorExtensions = 0;
  309. cfgDev.blockSize = 0;
  310. // System-specific defaults
  311. if (strequals(systemPresetName[SYS_PRESET_NONE], presetName))
  312. {
  313. // Preset name is empty, use default configuration
  314. m_sysPreset = SYS_PRESET_NONE;
  315. }
  316. else if (strequals(systemPresetName[SYS_PRESET_MAC], presetName))
  317. {
  318. m_sysPreset = SYS_PRESET_MAC;
  319. cfgSys.quirks = S2S_CFG_QUIRKS_APPLE;
  320. }
  321. else if (strequals(systemPresetName[SYS_PRESET_MACPLUS], presetName))
  322. {
  323. m_sysPreset = SYS_PRESET_MACPLUS;
  324. cfgSys.quirks = S2S_CFG_QUIRKS_APPLE;
  325. cfgSys.enableSelLatch = true;
  326. cfgSys.enableSCSI2 = false;
  327. cfgSys.selectionDelay = 0;
  328. if (g_log_debug) {
  329. g_log_debug = false;
  330. logmsg("Debug can not be enabled on the MacPlus preset.");
  331. }
  332. }
  333. else if (strequals(systemPresetName[SYS_PRESET_MPC3000], presetName))
  334. {
  335. m_sysPreset = SYS_PRESET_MPC3000;
  336. cfgSys.initPreDelay = 700;
  337. }
  338. else if (strequals(systemPresetName[SYS_PRESET_MEGASTE], presetName))
  339. {
  340. m_sysPreset = SYS_PRESET_MEGASTE;
  341. cfgSys.quirks = S2S_CFG_QUIRKS_NONE;
  342. cfgSys.mapLunsToIDs = true;
  343. cfgSys.enableParity = false;
  344. }
  345. else if (strequals(systemPresetName[SYS_PRESET_X68000], presetName) ||
  346. strequals(systemPresetName[SYS_PRESET_X68000_SCSI], presetName))
  347. {
  348. m_sysPreset = SYS_PRESET_X68000;
  349. cfgSys.selectionDelay = 0;
  350. cfgSys.quirks = S2S_CFG_QUIRKS_X68000;
  351. cfgSys.enableSCSI2 = false;
  352. cfgSys.maxSyncSpeed = 5;
  353. }
  354. else if (strequals(systemPresetName[SYS_PRESET_X68000_SASI], presetName))
  355. {
  356. m_sysPreset = SYS_PRESET_X68000_SASI;
  357. cfgSys.selectionDelay = 0;
  358. cfgSys.quirks = S2S_CFG_QUIRKS_X68000;
  359. cfgSys.enableSCSI2 = false;
  360. cfgSys.enableParity = false;
  361. cfgSys.maxSyncSpeed = 5;
  362. }
  363. else if (strequals(systemPresetName[SYS_PRESET_NeXT], presetName))
  364. {
  365. m_sysPreset = SYS_PRESET_NeXT;
  366. cfgSys.quirks = S2S_CFG_QUIRKS_NONE;
  367. cfgDev.sectorsPerTrack = 139;
  368. cfgDev.headsPerCylinder = 4;
  369. }
  370. else if (strequals(systemPresetName[SYS_PRESET_GENERIC], presetName))
  371. {
  372. m_sysPreset = SYS_PRESET_GENERIC;
  373. cfgSys.quirks = S2S_CFG_QUIRKS_NONE;
  374. }
  375. else
  376. {
  377. m_sysPreset = SYS_PRESET_NONE;
  378. logmsg("Unknown System preset name ", presetName, ", using default settings");
  379. }
  380. // Clear SCSI device strings
  381. memset(cfgDev.vendor, 0, sizeof(cfgDev.vendor));
  382. memset(cfgDev.prodId, 0, sizeof(cfgDev.prodId));
  383. memset(cfgDev.revision, 0, sizeof(cfgDev.revision));
  384. memset(cfgDev.serial, 0, sizeof(cfgDev.serial));
  385. // Read default setting overrides from ini file for each SCSI device
  386. readIniSCSIDeviceSetting(cfgDev, "SCSI");
  387. // Read settings from ini file that apply to all SCSI device
  388. cfgSys.quirks = ini_getl("SCSI", "Quirks", cfgSys.quirks, CONFIGFILE);
  389. cfgSys.selectionDelay = ini_getl("SCSI", "SelectionDelay", cfgSys.selectionDelay, CONFIGFILE);
  390. cfgSys.maxSyncSpeed = ini_getl("SCSI", "MaxSyncSpeed", cfgSys.maxSyncSpeed, CONFIGFILE);
  391. cfgSys.initPreDelay = ini_getl("SCSI", "InitPreDelay", cfgSys.initPreDelay, CONFIGFILE);
  392. cfgSys.initPostDelay = ini_getl("SCSI", "InitPostDelay", cfgSys.initPostDelay, CONFIGFILE);
  393. cfgSys.phyMode = ini_getl("SCSI", "PhyMode", cfgSys.phyMode, CONFIGFILE);
  394. cfgSys.enableUnitAttention = ini_getbool("SCSI", "EnableUnitAttention", cfgSys.enableUnitAttention, CONFIGFILE);
  395. cfgSys.enableSCSI2 = ini_getbool("SCSI", "EnableSCSI2", cfgSys.enableSCSI2, CONFIGFILE);
  396. cfgSys.enableSelLatch = ini_getbool("SCSI", "EnableSelLatch", cfgSys.enableSelLatch, CONFIGFILE);
  397. cfgSys.mapLunsToIDs = ini_getbool("SCSI", "MapLunsToIDs", cfgSys.mapLunsToIDs, CONFIGFILE);
  398. cfgSys.enableParity = ini_getbool("SCSI", "EnableParity", cfgSys.enableParity, CONFIGFILE);
  399. cfgSys.useFATAllocSize = ini_getbool("SCSI", "UseFATAllocSize", cfgSys.useFATAllocSize, CONFIGFILE);
  400. cfgSys.enableCDAudio = ini_getbool("SCSI", "EnableCDAudio", cfgSys.enableCDAudio, CONFIGFILE);
  401. cfgSys.maxVolume = ini_getl("SCSI", "MaxVolume", cfgSys.maxVolume, CONFIGFILE);
  402. cfgSys.enableUSBMassStorage = ini_getbool("SCSI", "EnableUSBMassStorage", cfgSys.enableUSBMassStorage, CONFIGFILE);
  403. cfgSys.usbMassStorageWaitPeriod = ini_getl("SCSI", "USBMassStorageWaitPeriod", cfgSys.usbMassStorageWaitPeriod, CONFIGFILE);
  404. cfgSys.usbMassStoragePresentImages = ini_getbool("SCSI", "USBMassStoragePresentImages", cfgSys.usbMassStoragePresentImages, CONFIGFILE);
  405. cfgSys.invertStatusLed = ini_getbool("SCSI", "InvertStatusLED", cfgSys.invertStatusLed, CONFIGFILE);
  406. char tmp[32];
  407. ini_gets("SCSI", "SpeedGrade", "", tmp, sizeof(tmp), CONFIGFILE);
  408. if (tmp[0] != '\0')
  409. {
  410. if (platform_reclock_supported())
  411. {
  412. cfgSys.speedGrade = stringToSpeedGrade(tmp, sizeof(tmp));
  413. }
  414. else
  415. {
  416. logmsg("Speed grade setting ignored, reclocking the MCU is not supported by this device");
  417. }
  418. }
  419. return &cfgSys;
  420. }
  421. scsi_device_settings_t* BlueSCSISettings::initDevice(uint8_t scsiId, S2S_CFG_TYPE type)
  422. {
  423. scsi_device_settings_t& cfg = m_dev[scsiId];
  424. char presetName[32] = {};
  425. char section[6] = "SCSI0";
  426. section[4] = '0' + scsiId;
  427. #ifdef BLUESCSI_HARDWARE_CONFIG
  428. const char *hwDevicePresetName = g_scsi_settings.getDevicePresetName(scsiId);
  429. if (g_hw_config.is_active())
  430. {
  431. if (strlen(hwDevicePresetName) < sizeof(presetName))
  432. {
  433. strncpy(presetName, hwDevicePresetName, sizeof(presetName) - 1);
  434. }
  435. }
  436. else
  437. #endif
  438. {
  439. ini_gets(section, "Device", "", presetName, sizeof(presetName), CONFIGFILE);
  440. }
  441. // Write default configuration from system setting initialization
  442. memcpy(&cfg, &m_dev[SCSI_SETTINGS_SYS_IDX], sizeof(cfg));
  443. setDefaultDriveInfo(scsiId, presetName, type);
  444. readIniSCSIDeviceSetting(cfg, section);
  445. if (cfg.serial[0] == '\0')
  446. {
  447. // Use SD card serial number
  448. cid_t sd_cid;
  449. uint32_t sd_sn = 0;
  450. if (SD.card()->readCID(&sd_cid))
  451. {
  452. sd_sn = sd_cid.psn();
  453. }
  454. memset(cfg.serial, 0, sizeof(cfg.serial));
  455. const char *nibble = "0123456789ABCDEF";
  456. cfg.serial[0] = nibble[(sd_sn >> 28) & 0xF];
  457. cfg.serial[1] = nibble[(sd_sn >> 24) & 0xF];
  458. cfg.serial[2] = nibble[(sd_sn >> 20) & 0xF];
  459. cfg.serial[3] = nibble[(sd_sn >> 16) & 0xF];
  460. cfg.serial[4] = nibble[(sd_sn >> 12) & 0xF];
  461. cfg.serial[5] = nibble[(sd_sn >> 8) & 0xF];
  462. cfg.serial[6] = nibble[(sd_sn >> 4) & 0xF];
  463. cfg.serial[7] = nibble[(sd_sn >> 0) & 0xF];
  464. }
  465. formatDriveInfoField(cfg.vendor, sizeof(cfg.vendor), cfg.rightAlignStrings);
  466. formatDriveInfoField(cfg.prodId, sizeof(cfg.prodId), cfg.rightAlignStrings);
  467. formatDriveInfoField(cfg.revision, sizeof(cfg.revision), cfg.rightAlignStrings);
  468. formatDriveInfoField(cfg.serial, sizeof(cfg.serial), true);
  469. return &cfg;
  470. }
  471. scsi_system_settings_t *BlueSCSISettings::getSystem()
  472. {
  473. return &m_sys;
  474. }
  475. scsi_device_settings_t *BlueSCSISettings::getDevice(uint8_t scsiId)
  476. {
  477. return &m_dev[scsiId];
  478. }
  479. scsi_system_preset_t BlueSCSISettings::getSystemPreset()
  480. {
  481. return m_sysPreset;
  482. }
  483. const char* BlueSCSISettings::getSystemPresetName()
  484. {
  485. return systemPresetName[m_sysPreset];
  486. }
  487. scsi_device_preset_t BlueSCSISettings::getDevicePreset(uint8_t scsiId)
  488. {
  489. return m_devPreset[scsiId];
  490. }
  491. const char* BlueSCSISettings::getDevicePresetName(uint8_t scsiId)
  492. {
  493. return devicePresetName[m_devPreset[scsiId]];
  494. }
  495. bluescsi_speed_grade_t BlueSCSISettings::stringToSpeedGrade(const char *speed_grade_target, size_t length)
  496. {
  497. bluescsi_speed_grade_t grade = bluescsi_speed_grade_t::SPEED_GRADE_DEFAULT;
  498. bool found_speed_grade = false;
  499. // search the list of speed grade strings for a matching target
  500. for (uint8_t i = 0; i < sizeof(speed_grade_strings)/sizeof(speed_grade_strings[0]); i++)
  501. {
  502. if (strncasecmp(speed_grade_target, speed_grade_strings[i], length) == 0)
  503. {
  504. grade = (bluescsi_speed_grade_t)i;
  505. found_speed_grade = true;
  506. break;
  507. }
  508. }
  509. if (!found_speed_grade)
  510. {
  511. logmsg("Setting \"", speed_grade_target, "\" does not match any known speed grade, using default");
  512. grade = SPEED_GRADE_DEFAULT;
  513. }
  514. return grade;
  515. }
  516. const char *BlueSCSISettings::getSpeedGradeString()
  517. {
  518. return speed_grade_strings[m_sys.speedGrade];
  519. }
  520. const bool BlueSCSISettings::isEjectButtonSet()
  521. {
  522. bool is_set = false;
  523. for (uint8_t i = 0; i < S2S_MAX_TARGETS; i++)
  524. {
  525. if (m_dev[i].ejectButton != 0)
  526. {
  527. is_set = true;
  528. break;
  529. }
  530. }
  531. return is_set;
  532. }