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