Emulation of multiple SCSI targets now working.
[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         config.flags = CONFIG_ENABLE_PARITY | CONFIG_ENABLE_UNIT_ATTENTION;
94         config.pad0 = 0;
95         config.sdSectorStart = 0;
96         config.scsiSectors = std::numeric_limits<uint32_t>::max();
97         config.bytesPerSector = 512;
98         config.sectorsPerTrack = 63;
99         config.headsPerCylinder = 255;
100         memcpy(config.vendor, " codesrc", 8);
101         memcpy(config.prodId, "         SCSI2SD", 16);
102         memcpy(config.revision, " 3.6", 4);
103         memcpy(config.serial, "1234567812345678", 16);
104
105         // Reserved fields, already set to 0
106         // config.reserved
107
108         // not supported yet.
109         // config.vpd
110
111         return config;
112 }
113
114
115 TargetConfig
116 ConfigUtil::fromBytes(const uint8_t* data)
117 {
118         TargetConfig result;
119         memcpy(&result, data, sizeof(TargetConfig));
120         result.sdSectorStart = toLE32(result.sdSectorStart);
121         result.scsiSectors = toLE32(result.scsiSectors);
122         result.bytesPerSector = toLE16(result.bytesPerSector);
123         result.sectorsPerTrack = toLE16(result.sectorsPerTrack);
124         result.headsPerCylinder = toLE16(result.headsPerCylinder);
125         return result;
126 }
127
128
129 std::vector<uint8_t>
130 ConfigUtil::toBytes(const TargetConfig& _config)
131 {
132         TargetConfig config(_config);
133         config.sdSectorStart = fromLE32(config.sdSectorStart);
134         config.scsiSectors = fromLE32(config.scsiSectors);
135         config.bytesPerSector = fromLE16(config.bytesPerSector);
136         config.sectorsPerTrack = fromLE16(config.sectorsPerTrack);
137         config.headsPerCylinder = fromLE16(config.headsPerCylinder);
138
139         const uint8_t* begin = reinterpret_cast<const uint8_t*>(&config);
140         return std::vector<uint8_t>(begin, begin + sizeof(config));
141 }
142