ConfigUtil.cc 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  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 "ConfigUtil.hh"
  18. #include <limits>
  19. #include <string.h>
  20. using namespace SCSI2SD;
  21. namespace
  22. {
  23. // Endian conversion routines.
  24. // The Cortex-M3 inside the Cypress PSoC 5LP is a
  25. // little-endian device.
  26. bool isHostLE()
  27. {
  28. union
  29. {
  30. int i;
  31. char c[sizeof(int)];
  32. } x;
  33. x.i = 1;
  34. return (x.c[0] == 1);
  35. }
  36. uint16_t toLE16(uint16_t in)
  37. {
  38. if (isHostLE())
  39. {
  40. return in;
  41. }
  42. else
  43. {
  44. return (in >> 8) | (in << 8);
  45. }
  46. }
  47. uint16_t fromLE16(uint16_t in)
  48. {
  49. return toLE16(in);
  50. }
  51. uint32_t toLE32(uint32_t in)
  52. {
  53. if (isHostLE())
  54. {
  55. return in;
  56. }
  57. else
  58. {
  59. return (in >> 24) |
  60. ((in >> 8) & 0xff00) |
  61. ((in << 8) & 0xff0000) |
  62. (in << 24);
  63. }
  64. }
  65. uint32_t fromLE32(uint32_t in)
  66. {
  67. return toLE32(in);
  68. }
  69. }
  70. TargetConfig
  71. ConfigUtil::Default(size_t targetIdx)
  72. {
  73. TargetConfig config;
  74. memset(&config, 0, sizeof(config));
  75. config.scsiId = targetIdx;
  76. if (targetIdx == 0)
  77. {
  78. config.scsiId = config.scsiId | CONFIG_TARGET_ENABLED;
  79. }
  80. config.deviceType = CONFIG_FIXED;
  81. // Default to maximum fail-safe options.
  82. config.flags = 0;// CONFIG_ENABLE_PARITY | CONFIG_ENABLE_UNIT_ATTENTION;
  83. config.pad0 = 0;
  84. config.sdSectorStart = 0;
  85. // Default to 2GB. Many systems have trouble with > 2GB disks, and
  86. // a few start to complain at 1GB.
  87. config.scsiSectors = 4194303; // 2GB - 1 sector
  88. config.bytesPerSector = 512;
  89. config.sectorsPerTrack = 63;
  90. config.headsPerCylinder = 255;
  91. memcpy(config.vendor, " codesrc", 8);
  92. memcpy(config.prodId, " SCSI2SD", 16);
  93. memcpy(config.revision, " 4.0", 4);
  94. memcpy(config.serial, "1234567812345678", 16);
  95. // Reserved fields, already set to 0
  96. // config.reserved
  97. // not supported yet.
  98. // config.vpd
  99. return config;
  100. }
  101. TargetConfig
  102. ConfigUtil::fromBytes(const uint8_t* data)
  103. {
  104. TargetConfig result;
  105. memcpy(&result, data, sizeof(TargetConfig));
  106. result.sdSectorStart = toLE32(result.sdSectorStart);
  107. result.scsiSectors = toLE32(result.scsiSectors);
  108. result.bytesPerSector = toLE16(result.bytesPerSector);
  109. result.sectorsPerTrack = toLE16(result.sectorsPerTrack);
  110. result.headsPerCylinder = toLE16(result.headsPerCylinder);
  111. return result;
  112. }
  113. std::vector<uint8_t>
  114. ConfigUtil::toBytes(const TargetConfig& _config)
  115. {
  116. TargetConfig config(_config);
  117. config.sdSectorStart = fromLE32(config.sdSectorStart);
  118. config.scsiSectors = fromLE32(config.scsiSectors);
  119. config.bytesPerSector = fromLE16(config.bytesPerSector);
  120. config.sectorsPerTrack = fromLE16(config.sectorsPerTrack);
  121. config.headsPerCylinder = fromLE16(config.headsPerCylinder);
  122. const uint8_t* begin = reinterpret_cast<const uint8_t*>(&config);
  123. return std::vector<uint8_t>(begin, begin + sizeof(config));
  124. }