Fix bug "protocol error" bug when saving config settings.
[SCSI2SD-V6.git] / src / firmware / config.c
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 "config.h"
19 #include "led.h"
20
21 #include "scsi.h"
22 #include "scsiPhy.h"
23 #include "sd.h"
24 #include "disk.h"
25 #include "trace.h"
26 #include "bootloader.h"
27 #include "bsp.h"
28
29 #include "../../include/scsi2sd.h"
30 #include "../../include/hidpacket.h"
31
32 #include "usb_device/usb_device.h"
33 #include "usb_device/usbd_hid.h"
34 #include "usb_device/usbd_composite.h"
35 #include "bsp_driver_sd.h"
36
37
38 #include <string.h>
39
40 static const uint16_t FIRMWARE_VERSION = 0x0607;
41
42 // 1 flash row
43 static const uint8_t DEFAULT_CONFIG[128] =
44 {
45 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3F, 0x00,
46 0x00, 0x02, 0x3F, 0x00, 0xFF, 0x00, 0x20, 0x63, 0x6F, 0x64, 0x65, 0x73,
47 0x72, 0x63, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53,
48 0x43, 0x53, 0x49, 0x32, 0x53, 0x44, 0x20, 0x31, 0x2E, 0x30, 0x31, 0x32,
49 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
50 0x37, 0x38, 0x00, 0x00
51 };
52
53
54 static uint8_t s2s_cfg[S2S_CFG_SIZE] S2S_DMA_ALIGN;
55 static uint8_t configDmaBuf[512] S2S_DMA_ALIGN; // For SD card writes.
56
57
58 enum USB_STATE
59 {
60 USB_IDLE,
61 USB_DATA_SENT
62 };
63
64
65 static int usbInEpState;
66
67 void s2s_configInit(S2S_BoardCfg* config)
68 {
69
70 usbInEpState = USB_IDLE;
71
72
73 if ((blockDev.state & DISK_PRESENT) && sdDev.capacity)
74 {
75 int cfgSectors = (S2S_CFG_SIZE + 511) / 512;
76 BSP_SD_ReadBlocks_DMA(
77 (uint32_t*) &s2s_cfg[0],
78 (sdDev.capacity - cfgSectors) * 512ll,
79 512,
80 cfgSectors);
81
82 memcpy(config, s2s_cfg, sizeof(S2S_BoardCfg));
83
84 if (memcmp(config->magic, "BCFG", 4))
85 {
86 // Invalid SD card config, use default.
87 memset(&s2s_cfg[0], 0, S2S_CFG_SIZE);
88 memcpy(config, s2s_cfg, sizeof(S2S_BoardCfg));
89 memcpy(config->magic, "BCFG", 4);
90 config->selectionDelay = 255; // auto
91 config->flags6 = S2S_CFG_ENABLE_TERMINATOR;
92
93 memcpy(
94 &s2s_cfg[0] + sizeof(S2S_BoardCfg),
95 DEFAULT_CONFIG,
96 sizeof(S2S_TargetCfg));
97 }
98 }
99 else
100 {
101 // No SD card, use existing config if valid
102 if (memcmp(config->magic, "BCFG", 4))
103 {
104 // Not valid, use empty config with no disks.
105 memset(&s2s_cfg[0], 0, S2S_CFG_SIZE);
106 memcpy(config, s2s_cfg, sizeof(S2S_BoardCfg));
107 config->selectionDelay = 255; // auto
108 config->flags6 = S2S_CFG_ENABLE_TERMINATOR;
109 }
110 }
111
112 }
113
114
115 static void
116 pingCommand()
117 {
118 uint8_t response[] =
119 {
120 S2S_CFG_STATUS_GOOD
121 };
122 hidPacket_send(response, sizeof(response));
123 }
124
125 static void
126 sdInfoCommand()
127 {
128 uint8_t response[sizeof(sdDev.csd) + sizeof(sdDev.cid)];
129 memcpy(response, sdDev.csd, sizeof(sdDev.csd));
130 memcpy(response + sizeof(sdDev.csd), sdDev.cid, sizeof(sdDev.cid));
131
132 hidPacket_send(response, sizeof(response));
133 }
134
135
136 static void
137 scsiTestCommand()
138 {
139 int resultCode = scsiSelfTest();
140 uint8_t response[] =
141 {
142 resultCode == 0 ? S2S_CFG_STATUS_GOOD : S2S_CFG_STATUS_ERR,
143 resultCode
144 };
145 hidPacket_send(response, sizeof(response));
146 }
147
148 static void
149 scsiDevInfoCommand()
150 {
151 uint8_t response[] =
152 {
153 FIRMWARE_VERSION >> 8,
154 FIRMWARE_VERSION & 0xff,
155 sdDev.capacity >> 24,
156 sdDev.capacity >> 16,
157 sdDev.capacity >> 8,
158 sdDev.capacity
159 };
160 hidPacket_send(response, sizeof(response));
161 }
162
163 static void
164 debugCommand()
165 {
166 uint8_t response[32];
167 memcpy(&response, &scsiDev.cdb, 12);
168 response[12] = scsiDev.msgIn;
169 response[13] = scsiDev.msgOut;
170 response[14] = scsiDev.lastStatus;
171 response[15] = scsiDev.lastSense;
172 response[16] = scsiDev.phase;
173 response[17] = scsiStatusBSY();
174 response[18] = scsiStatusSEL();
175 response[19] = scsiStatusATN();
176 response[20] = scsiStatusRST();
177 response[21] = scsiDev.rstCount;
178 response[22] = scsiDev.selCount;
179 response[23] = scsiDev.msgCount;
180 response[24] = scsiDev.cmdCount;
181 response[25] = scsiDev.watchdogTick;
182 response[26] = blockDev.state;
183 response[27] = scsiDev.lastSenseASC >> 8;
184 response[28] = scsiDev.lastSenseASC;
185 response[29] = *SCSI_STS_DBX;
186 response[30] = LastTrace;
187 response[31] = scsiStatusACK();
188 hidPacket_send(response, sizeof(response));
189 }
190
191 static void
192 sdWriteCommand(const uint8_t* cmd, size_t cmdSize)
193 {
194 if (cmdSize < 517)
195 {
196 return; // ignore.
197 }
198 uint32_t lba =
199 (((uint32_t)cmd[1]) << 24) |
200 (((uint32_t)cmd[2]) << 16) |
201 (((uint32_t)cmd[3]) << 8) |
202 ((uint32_t)cmd[4]);
203
204 memcpy(configDmaBuf, &cmd[5], 512);
205 BSP_SD_WriteBlocks_DMA((uint32_t*) configDmaBuf, lba * 512ll, 512, 1);
206
207 uint8_t response[] =
208 {
209 S2S_CFG_STATUS_GOOD
210 };
211 hidPacket_send(response, sizeof(response));
212 }
213
214 static void
215 sdReadCommand(const uint8_t* cmd, size_t cmdSize)
216 {
217 if (cmdSize < 5)
218 {
219 return; // ignore.
220 }
221 uint32_t lba =
222 (((uint32_t)cmd[1]) << 24) |
223 (((uint32_t)cmd[2]) << 16) |
224 (((uint32_t)cmd[3]) << 8) |
225 ((uint32_t)cmd[4]);
226
227 BSP_SD_ReadBlocks_DMA((uint32_t*) configDmaBuf, lba * 512ll, 512, 1);
228 hidPacket_send(configDmaBuf, 512);
229 }
230
231 static void
232 processCommand(const uint8_t* cmd, size_t cmdSize)
233 {
234 switch (cmd[0])
235 {
236 case S2S_CMD_PING:
237 pingCommand();
238 break;
239
240 case S2S_CMD_REBOOT:
241 s2s_enterBootloader();
242 break;
243
244 case S2S_CMD_SDINFO:
245 sdInfoCommand();
246 break;
247
248 case S2S_CMD_SCSITEST:
249 scsiTestCommand();
250 break;
251
252 case S2S_CMD_DEVINFO:
253 scsiDevInfoCommand();
254 break;
255
256 case S2S_CMD_SD_WRITE:
257 sdWriteCommand(cmd, cmdSize);
258 break;
259
260 case S2S_CMD_SD_READ:
261 sdReadCommand(cmd, cmdSize);
262 break;
263
264 case S2S_CMD_DEBUG:
265 debugCommand();
266 break;
267
268 case S2S_CMD_NONE: // invalid
269 default:
270 break;
271 }
272 }
273
274 void s2s_configPoll()
275 {
276 if (!USBD_Composite_IsConfigured(&hUsbDeviceFS))
277 {
278 usbInEpState = USB_IDLE;
279 return;
280 }
281
282 if (USBD_HID_IsReportReady(&hUsbDeviceFS))
283 {
284 s2s_ledOn();
285
286 // The host sent us some data!
287 uint8_t hidBuffer[USBHID_LEN];
288 int byteCount = USBD_HID_GetReport(&hUsbDeviceFS, hidBuffer, sizeof(hidBuffer));
289 hidPacket_recv(hidBuffer, byteCount);
290
291 size_t cmdSize;
292 const uint8_t* cmd = hidPacket_getPacket(&cmdSize);
293 if (cmd && (cmdSize > 0))
294 {
295 processCommand(cmd, cmdSize);
296 }
297
298 s2s_ledOff();
299 }
300
301 switch (usbInEpState)
302 {
303 case USB_IDLE:
304 {
305 uint8_t hidBuffer[USBHID_LEN];
306 const uint8_t* nextChunk = hidPacket_getHIDBytes(hidBuffer);
307
308 if (nextChunk)
309 {
310 USBD_HID_SendReport (&hUsbDeviceFS, nextChunk, sizeof(hidBuffer));
311 usbInEpState = USB_DATA_SENT;
312 }
313 }
314 break;
315
316 case USB_DATA_SENT:
317 if (!USBD_HID_IsBusy(&hUsbDeviceFS))
318 {
319 // Data accepted.
320 usbInEpState = USB_IDLE;
321 }
322 break;
323 }
324
325 }
326
327
328
329 // Public method for storing MODE SELECT results.
330 void s2s_configSave(int scsiId, uint16_t bytesPerSector)
331 {
332 S2S_TargetCfg* cfg = (S2S_TargetCfg*) s2s_getConfigById(scsiId);
333 cfg->bytesPerSector = bytesPerSector;
334
335 BSP_SD_WriteBlocks_DMA(
336 (uint32_t*) &s2s_cfg[0],
337 (sdDev.capacity - S2S_CFG_SIZE) * 512ll,
338 512,
339 (S2S_CFG_SIZE + 511) / 512);
340 }
341
342
343 const S2S_TargetCfg* s2s_getConfigByIndex(int i)
344 {
345 return (const S2S_TargetCfg*)
346 (s2s_cfg + sizeof(S2S_BoardCfg) + (i * sizeof(S2S_TargetCfg)));
347 }
348
349 const S2S_TargetCfg* s2s_getConfigById(int scsiId)
350 {
351 int i;
352 for (i = 0; i < S2S_MAX_TARGETS; ++i)
353 {
354 const S2S_TargetCfg* tgt = s2s_getConfigByIndex(i);
355 if ((tgt->scsiId & S2S_CFG_TARGET_ID_BITS) == scsiId)
356 {
357 return tgt;
358 }
359 }
360 return NULL;
361
362 }
363