Small compatibility improvements, and added scsi2sd-monitor test program
[SCSI2SD-V6.git] / software / scsi2sd-util / ConfigUtil.cc
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
18 #include "ConfigUtil.hh"
19
20 #include <limits>
21
22 #include <string.h>
23
24
25 using namespace SCSI2SD;
26
27 namespace
28 {
29 // Endian conversion routines.
30 // The Cortex-M3 inside the Cypress PSoC 5LP is a
31 // little-endian device.
32
33 bool isHostLE()
34 {
35 union
36 {
37 int i;
38 char c[sizeof(int)];
39 } x;
40 x.i = 1;
41 return (x.c[0] == 1);
42 }
43
44 uint16_t toLE16(uint16_t in)
45 {
46 if (isHostLE())
47 {
48 return in;
49 }
50 else
51 {
52 return (in >> 8) | (in << 8);
53 }
54 }
55 uint16_t fromLE16(uint16_t in)
56 {
57 return toLE16(in);
58 }
59
60 uint32_t toLE32(uint32_t in)
61 {
62 if (isHostLE())
63 {
64 return in;
65 }
66 else
67 {
68 return (in >> 24) |
69 ((in >> 8) & 0xff00) |
70 ((in << 8) & 0xff0000) |
71 (in << 24);
72 }
73 }
74 uint32_t fromLE32(uint32_t in)
75 {
76 return toLE32(in);
77 }
78
79 }
80
81 TargetConfig
82 ConfigUtil::Default(size_t targetIdx)
83 {
84 TargetConfig config;
85 memset(&config, 0, sizeof(config));
86
87 config.scsiId = targetIdx;
88 if (targetIdx == 0)
89 {
90 config.scsiId = config.scsiId | CONFIG_TARGET_ENABLED;
91 }
92 config.deviceType = CONFIG_FIXED;
93
94 // Default to maximum fail-safe options.
95 config.flags = 0;// CONFIG_ENABLE_PARITY | CONFIG_ENABLE_UNIT_ATTENTION;
96 config.deviceTypeModifier = 0;
97 config.sdSectorStart = 0;
98
99 // Default to 2GB. Many systems have trouble with > 2GB disks, and
100 // a few start to complain at 1GB.
101 config.scsiSectors = 4194303; // 2GB - 1 sector
102 config.bytesPerSector = 512;
103 config.sectorsPerTrack = 63;
104 config.headsPerCylinder = 255;
105 memcpy(config.vendor, " codesrc", 8);
106 memcpy(config.prodId, " SCSI2SD", 16);
107 memcpy(config.revision, " 4.2", 4);
108 memcpy(config.serial, "1234567812345678", 16);
109
110 // Reserved fields, already set to 0
111 // config.reserved
112
113 // not supported yet.
114 // config.vpd
115
116 return config;
117 }
118
119
120 TargetConfig
121 ConfigUtil::fromBytes(const uint8_t* data)
122 {
123 TargetConfig result;
124 memcpy(&result, data, sizeof(TargetConfig));
125 result.sdSectorStart = toLE32(result.sdSectorStart);
126 result.scsiSectors = toLE32(result.scsiSectors);
127 result.bytesPerSector = toLE16(result.bytesPerSector);
128 result.sectorsPerTrack = toLE16(result.sectorsPerTrack);
129 result.headsPerCylinder = toLE16(result.headsPerCylinder);
130 return result;
131 }
132
133
134 std::vector<uint8_t>
135 ConfigUtil::toBytes(const TargetConfig& _config)
136 {
137 TargetConfig config(_config);
138 config.sdSectorStart = fromLE32(config.sdSectorStart);
139 config.scsiSectors = fromLE32(config.scsiSectors);
140 config.bytesPerSector = fromLE16(config.bytesPerSector);
141 config.sectorsPerTrack = fromLE16(config.sectorsPerTrack);
142 config.headsPerCylinder = fromLE16(config.headsPerCylinder);
143
144 const uint8_t* begin = reinterpret_cast<const uint8_t*>(&config);
145 return std::vector<uint8_t>(begin, begin + sizeof(config));
146 }
147
148 /*
149 wxXmlNode*
150 ConfigUtil::toXML(const TargetConfig& config)
151 {
152 wxXmlNode* target = new wxXmlNode(wxXML_ELEMENT_NODE, "SCSITarget");
153
154 {
155 std::stringstream s; s << scsiId & CONFIG_TARGET_ID_BITS;
156 target.AddAttribute("id", s.str());
157 }
158 {
159 std::stringstream s; s << config.deviceType;
160 new wxXmlNode(
161 new wxXmlNode(target, wxXML_ELEMENT_NODE, "deviceType"),
162 wxXML_TEXT_NODE, "", s.str());
163 }
164
165 {
166 std::stringstream s; s << "0x" << std::hex << config.deviceTypeModifier;
167 new wxXmlNode(
168 new wxXmlNode(target, wxXML_ELEMENT_NODE, "deviceTypeModifier"),
169 wxXML_TEXT_NODE, "", s.str());
170 }
171
172 wxXmlNode* flags(new wxXmlNode(target, wxXML_ELEMENT_NODE, "flags"));
173
174 new wxXmlNode(
175 new wxXmlNode(flags, wxXML_ELEMENT_NODE, "enabled"),
176 wxXML_TEXT_NODE,
177 "",
178 config.scsiId & CONFIG_TARGET_ENABLED ? "true" : "false");
179
180 "<unitAttention>" <<
181 (config.flags & CONFIG_ENABLE_UNIT_ATTENTION ? "true" : "false") <<
182 "</unitAttention>\n" <<
183 "<parity>" <<
184 (config.flags & CONFIG_ENABLE_PARITY ? "true" : "false") <<
185 "</parity>\n" <<
186
187 "<sdSectorStart>" << config.sdSectorStart << "</sdSectorStart>\n" <<
188 "<scsiSectors>" << config.scsiSectors << "</scsiSectors>\n" <<
189 "<bytesPerSector>" << config.bytesPerSector << "</bytesPerSector>\n" <<
190 "<sectorsPerTrack>" << config.sectorsPerTrack<< "</sectorsPerTrack>\n" <<
191 "<headsPerCylinder>" << config.headsPerCylinder << "</headsPerCylinder>\n" <<
192
193 "<vendor>" << std::string(config.vendor, 8) << "</vendor>" <<
194 "<prodId>" << std::string(config.prodId, 16) << "</prodId>" <<
195 "<revision>" << std::string(config.revision, 4) << "</revision>" <<
196 "<serial>" << std::string(config.serial, 16) << "</serial>" <<
197
198 "</SCSITarget>";
199 }
200
201 void
202 ConfigUtil::deserialise(const std::string& in)
203 {
204
205 }
206 */