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