1015ae3445cdcfbcad25987177f7a12c152b2ab5
[SCSI2SD-V6.git] / src / firmware / config.c
1 //      Copyright (C) 2014 Michael McMaster <michael@codesrc.com>\r
2 //\r
3 //      This file is part of SCSI2SD.\r
4 //\r
5 //      SCSI2SD is free software: you can redistribute it and/or modify\r
6 //      it under the terms of the GNU General Public License as published by\r
7 //      the Free Software Foundation, either version 3 of the License, or\r
8 //      (at your option) any later version.\r
9 //\r
10 //      SCSI2SD is distributed in the hope that it will be useful,\r
11 //      but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12 //      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13 //      GNU General Public License for more details.\r
14 //\r
15 //      You should have received a copy of the GNU General Public License\r
16 //      along with SCSI2SD.  If not, see <http://www.gnu.org/licenses/>.\r
17 \r
18 #include "config.h"\r
19 #include "debug.h"\r
20 #include "led.h"\r
21 \r
22 #include "scsi.h"\r
23 #include "scsiPhy.h"\r
24 #include "sd.h"\r
25 #include "disk.h"\r
26 #include "trace.h"\r
27 #include "bootloader.h"\r
28 #include "bsp.h"\r
29 \r
30 #include "../../include/scsi2sd.h"\r
31 #include "../../include/hidpacket.h"\r
32 \r
33 #include "usb_device/usb_device.h"\r
34 #include "usb_device/usbd_hid.h"\r
35 #include "usb_device/usbd_composite.h"\r
36 #include "bsp_driver_sd.h"\r
37 \r
38 \r
39 #include <string.h>\r
40 \r
41 static const uint16_t FIRMWARE_VERSION = 0x0600;\r
42 \r
43 // 1 flash row\r
44 static const uint8_t DEFAULT_CONFIG[128] =\r
45 {\r
46         0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3F, 0x00,\r
47         0x00, 0x02, 0x3F, 0x00, 0xFF, 0x00, 0x20, 0x63, 0x6F, 0x64, 0x65, 0x73,\r
48         0x72, 0x63, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53,\r
49         0x43, 0x53, 0x49, 0x32, 0x53, 0x44, 0x20, 0x31, 0x2E, 0x30, 0x31, 0x32,\r
50         0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,\r
51         0x37, 0x38, 0x00, 0x00\r
52 };\r
53 \r
54 \r
55 static uint8_t s2s_cfg[S2S_CFG_SIZE] S2S_DMA_ALIGN;\r
56 \r
57 \r
58 enum USB_STATE\r
59 {\r
60         USB_IDLE,\r
61         USB_DATA_SENT\r
62 };\r
63 \r
64 \r
65 static int usbInEpState;\r
66 #if 0\r
67 static int usbDebugEpState;\r
68 #endif\r
69 static int usbReady; // TODO MM REMOVE. Unused ?\r
70 \r
71 static void initS2S_BoardCfg(S2S_BoardCfg* config) {\r
72         if (memcmp(config->magic, "BCFG", 4)) {\r
73                 config->selectionDelay = 255; // auto\r
74                 config->flags6 = S2S_CFG_ENABLE_TERMINATOR;\r
75 \r
76                 memcpy(\r
77                         s2s_cfg + sizeof(S2S_BoardCfg),\r
78                         DEFAULT_CONFIG,\r
79                         sizeof(S2S_TargetCfg));\r
80         }\r
81 }\r
82 \r
83 \r
84 void s2s_configInit(S2S_BoardCfg* config)\r
85 {\r
86 \r
87         usbInEpState = USB_IDLE;\r
88         usbReady = 0; // We don't know if host is connected yet.\r
89 \r
90 \r
91         if (blockDev.state & DISK_PRESENT && sdDev.capacity)\r
92         {\r
93                 int cfgSectors = (S2S_CFG_SIZE + 511) / 512;\r
94                 BSP_SD_ReadBlocks_DMA(\r
95                         (uint32_t*) &s2s_cfg[0],\r
96                         (sdDev.capacity - cfgSectors) * 512ll,\r
97                         512,\r
98                         cfgSectors);\r
99 \r
100                 memcpy(config, s2s_cfg, sizeof(S2S_BoardCfg));\r
101         }\r
102 \r
103         initS2S_BoardCfg(config);\r
104 \r
105         scsiPhyConfig();\r
106 }\r
107 \r
108 \r
109 static void\r
110 pingCommand()\r
111 {\r
112         uint8_t response[] =\r
113         {\r
114                 S2S_CFG_STATUS_GOOD\r
115         };\r
116         hidPacket_send(response, sizeof(response));\r
117 }\r
118 \r
119 static void\r
120 sdInfoCommand()\r
121 {\r
122         uint8_t response[sizeof(sdDev.csd) + sizeof(sdDev.cid)];\r
123         memcpy(response, sdDev.csd, sizeof(sdDev.csd));\r
124         memcpy(response + sizeof(sdDev.csd), sdDev.cid, sizeof(sdDev.cid));\r
125 \r
126         hidPacket_send(response, sizeof(response));\r
127 }\r
128 \r
129 \r
130 static void\r
131 scsiTestCommand()\r
132 {\r
133         int resultCode = 0; // TODO scsiSelfTest();\r
134         uint8_t response[] =\r
135         {\r
136                 resultCode == 0 ? S2S_CFG_STATUS_GOOD : S2S_CFG_STATUS_ERR,\r
137                 resultCode\r
138         };\r
139         hidPacket_send(response, sizeof(response));\r
140 }\r
141 \r
142 static void\r
143 scsiDevInfoCommand()\r
144 {\r
145         uint8_t response[] =\r
146         {\r
147                 FIRMWARE_VERSION >> 8,\r
148                 FIRMWARE_VERSION & 0xff,\r
149                 sdDev.capacity >> 24,\r
150                 sdDev.capacity >> 16,\r
151                 sdDev.capacity >> 8,\r
152                 sdDev.capacity\r
153         };\r
154         hidPacket_send(response, sizeof(response));\r
155 }\r
156 \r
157 \r
158 static void\r
159 sdWriteCommand(const uint8_t* cmd, size_t cmdSize)\r
160 {\r
161         if (cmdSize < 517)\r
162         {\r
163                 return; // ignore.\r
164         }\r
165         uint32_t lba =\r
166                 (((uint32_t)cmd[1]) << 24) |\r
167                 (((uint32_t)cmd[2]) << 16) |\r
168                 (((uint32_t)cmd[3]) << 8) |\r
169                 ((uint32_t)cmd[4]);\r
170 \r
171         // Must be aligned.\r
172         uint8_t buf[512] S2S_DMA_ALIGN;\r
173         memcpy(buf, &cmd[5], 512);\r
174         BSP_SD_WriteBlocks_DMA((uint32_t*) buf, lba * 512ll, 512, 1);\r
175 \r
176         uint8_t response[] =\r
177         {\r
178                 S2S_CFG_STATUS_GOOD\r
179         };\r
180         hidPacket_send(response, sizeof(response));\r
181 }\r
182 \r
183 static void\r
184 sdReadCommand(const uint8_t* cmd, size_t cmdSize)\r
185 {\r
186         if (cmdSize < 5)\r
187         {\r
188                 return; // ignore.\r
189         }\r
190         uint32_t lba =\r
191                 (((uint32_t)cmd[1]) << 24) |\r
192                 (((uint32_t)cmd[2]) << 16) |\r
193                 (((uint32_t)cmd[3]) << 8) |\r
194                 ((uint32_t)cmd[4]);\r
195 \r
196         BSP_SD_ReadBlocks_DMA((uint32_t*) cmd, lba * 512ll, 512, 1);\r
197         hidPacket_send(cmd, 512);\r
198 }\r
199 \r
200 static void\r
201 processCommand(const uint8_t* cmd, size_t cmdSize)\r
202 {\r
203         switch (cmd[0])\r
204         {\r
205         case S2S_CMD_PING:\r
206                 pingCommand();\r
207                 break;\r
208 \r
209         case S2S_CMD_REBOOT:\r
210                 s2s_enterBootloader();\r
211                 break;\r
212 \r
213         case S2S_CMD_SDINFO:\r
214                 sdInfoCommand();\r
215                 break;\r
216 \r
217         case S2S_CMD_SCSITEST:\r
218                 scsiTestCommand();\r
219                 break;\r
220 \r
221         case S2S_CMD_DEVINFO:\r
222                 scsiDevInfoCommand();\r
223                 break;\r
224 \r
225         case S2S_CMD_SD_WRITE:\r
226                 sdWriteCommand(cmd, cmdSize);\r
227                 break;\r
228 \r
229         case S2S_CMD_SD_READ:\r
230                 sdReadCommand(cmd, cmdSize);\r
231                 break;\r
232 \r
233         case S2S_CMD_NONE: // invalid\r
234         default:\r
235                 break;\r
236         }\r
237 }\r
238 \r
239 void s2s_configPoll()\r
240 {\r
241         if (!USBD_Composite_IsConfigured(&hUsbDeviceFS))\r
242         {\r
243                 usbInEpState = USB_IDLE;\r
244                 return;\r
245         }\r
246 \r
247         if (USBD_HID_IsReportReady(&hUsbDeviceFS))\r
248         {\r
249                 s2s_ledOn();\r
250 \r
251                 // The host sent us some data!\r
252                 uint8_t hidBuffer[USBHID_LEN];\r
253                 int byteCount = USBD_HID_GetReport(&hUsbDeviceFS, hidBuffer, sizeof(hidBuffer));\r
254                 hidPacket_recv(hidBuffer, byteCount);\r
255 \r
256                 size_t cmdSize;\r
257                 const uint8_t* cmd = hidPacket_getPacket(&cmdSize);\r
258                 if (cmd && (cmdSize > 0))\r
259                 {\r
260                         processCommand(cmd, cmdSize);\r
261                 }\r
262 \r
263                 s2s_ledOff();\r
264         }\r
265 \r
266         switch (usbInEpState)\r
267         {\r
268         case USB_IDLE:\r
269                 {\r
270                         uint8_t hidBuffer[USBHID_LEN];\r
271                         const uint8_t* nextChunk = hidPacket_getHIDBytes(hidBuffer);\r
272 \r
273                         if (nextChunk)\r
274                         {\r
275                                 USBD_HID_SendReport (&hUsbDeviceFS, nextChunk, sizeof(hidBuffer));\r
276                                 usbInEpState = USB_DATA_SENT;\r
277                         }\r
278                 }\r
279                 break;\r
280 \r
281         case USB_DATA_SENT:\r
282                 if (!USBD_HID_IsBusy(&hUsbDeviceFS))\r
283                 {\r
284                         // Data accepted.\r
285                         usbInEpState = USB_IDLE;\r
286                 }\r
287                 break;\r
288         }\r
289 \r
290 }\r
291 \r
292 void debugPoll()\r
293 {\r
294 #if 0\r
295         if (!usbReady)\r
296         {\r
297                 return;\r
298         }\r
299 \r
300         if(USBFS_GetEPState(USB_EP_COMMAND) == USBFS_OUT_BUFFER_FULL)\r
301         {\r
302                 // The host sent us some data!\r
303                 int byteCount = USBFS_GetEPCount(USB_EP_COMMAND);\r
304                 USBFS_ReadOutEP(USB_EP_COMMAND, (uint8 *)&hidBuffer, byteCount);\r
305 \r
306                 if (byteCount >= 1 &&\r
307                         hidBuffer[0] == 0x01)\r
308                 {\r
309                         // Reboot command.\r
310                         Bootloadable_1_Load();\r
311                 }\r
312 \r
313                 // Allow the host to send us another command.\r
314                 // (assuming we didn't reboot outselves)\r
315                 USBFS_EnableOutEP(USB_EP_COMMAND);\r
316         }\r
317 \r
318         switch (usbDebugEpState)\r
319         {\r
320         case USB_IDLE:\r
321                 memcpy(&hidBuffer, &scsiDev.cdb, 12);\r
322                 hidBuffer[12] = scsiDev.msgIn;\r
323                 hidBuffer[13] = scsiDev.msgOut;\r
324                 hidBuffer[14] = scsiDev.lastStatus;\r
325                 hidBuffer[15] = scsiDev.lastSense;\r
326                 hidBuffer[16] = scsiDev.phase;\r
327                 hidBuffer[17] = SCSI_ReadFilt(SCSI_Filt_BSY);\r
328                 hidBuffer[18] = SCSI_ReadFilt(SCSI_Filt_SEL);\r
329                 hidBuffer[19] = SCSI_ReadFilt(SCSI_Filt_ATN);\r
330                 hidBuffer[20] = SCSI_ReadFilt(SCSI_Filt_RST);\r
331                 hidBuffer[21] = scsiDev.rstCount;\r
332                 hidBuffer[22] = scsiDev.selCount;\r
333                 hidBuffer[23] = scsiDev.msgCount;\r
334                 hidBuffer[24] = scsiDev.cmdCount;\r
335                 hidBuffer[25] = scsiDev.watchdogTick;\r
336                 hidBuffer[26] = blockDev.state;\r
337                 hidBuffer[27] = scsiDev.lastSenseASC >> 8;\r
338                 hidBuffer[28] = scsiDev.lastSenseASC;\r
339                 hidBuffer[29] = scsiReadDBxPins();\r
340                 hidBuffer[30] = LastTrace;\r
341 \r
342                 hidBuffer[58] = sdDev.capacity >> 24;\r
343                 hidBuffer[59] = sdDev.capacity >> 16;\r
344                 hidBuffer[60] = sdDev.capacity >> 8;\r
345                 hidBuffer[61] = sdDev.capacity;\r
346 \r
347                 hidBuffer[62] = FIRMWARE_VERSION >> 8;\r
348                 hidBuffer[63] = FIRMWARE_VERSION;\r
349 \r
350                 USBFS_LoadInEP(USB_EP_DEBUG, (uint8 *)&hidBuffer, sizeof(hidBuffer));\r
351                 usbDebugEpState = USB_DATA_SENT;\r
352                 break;\r
353 \r
354         case USB_DATA_SENT:\r
355                 if (USBFS_bGetEPAckState(USB_EP_DEBUG))\r
356                 {\r
357                         // Data accepted.\r
358                         usbDebugEpState = USB_IDLE;\r
359                 }\r
360                 break;\r
361         }\r
362 #endif\r
363 }\r
364 \r
365 #if 0\r
366 CY_ISR(debugTimerISR)\r
367 {\r
368         Debug_Timer_ReadStatusRegister();\r
369         Debug_Timer_Interrupt_ClearPending();\r
370         uint8 savedIntrStatus = CyEnterCriticalSection();\r
371         debugPoll();\r
372         CyExitCriticalSection(savedIntrStatus);\r
373 }\r
374 #endif\r
375 \r
376 void s2s_debugInit()\r
377 {\r
378 #if 0\r
379         Debug_Timer_Interrupt_StartEx(debugTimerISR);\r
380         Debug_Timer_Start();\r
381 #endif\r
382 }\r
383 \r
384 void debugPause()\r
385 {\r
386 #if 0\r
387         Debug_Timer_Stop();\r
388 #endif\r
389 }\r
390 \r
391 void debugResume()\r
392 {\r
393 #if 0\r
394         Debug_Timer_Start();\r
395 #endif\r
396 }\r
397 \r
398 int isDebugEnabled()\r
399 {\r
400         return usbReady;\r
401 }\r
402 \r
403 // Public method for storing MODE SELECT results.\r
404 void s2s_configSave(int scsiId, uint16_t bytesPerSector)\r
405 {\r
406         S2S_TargetCfg* cfg = (S2S_TargetCfg*) s2s_getConfigById(scsiId);\r
407         cfg->bytesPerSector = bytesPerSector;\r
408 \r
409         BSP_SD_WriteBlocks_DMA(\r
410                 (uint32_t*) &s2s_cfg[0],\r
411                 (sdDev.capacity - S2S_CFG_SIZE) * 512ll,\r
412                 512,\r
413                 (S2S_CFG_SIZE + 511) / 512);\r
414 }\r
415 \r
416 \r
417 const S2S_TargetCfg* s2s_getConfigByIndex(int i)\r
418 {\r
419         return (const S2S_TargetCfg*)\r
420                 (s2s_cfg + sizeof(S2S_BoardCfg) + (i * sizeof(S2S_TargetCfg)));\r
421 }\r
422 \r
423 const S2S_TargetCfg* s2s_getConfigById(int scsiId)\r
424 {\r
425         int i;\r
426         for (i = 0; i < S2S_MAX_TARGETS; ++i)\r
427         {\r
428                 const S2S_TargetCfg* tgt = s2s_getConfigByIndex(i);\r
429                 if ((tgt->scsiId & S2S_CFG_TARGET_ID_BITS) == scsiId)\r
430                 {\r
431                         return tgt;\r
432                 }\r
433         }\r
434         return NULL;\r
435 \r
436 }\r
437 \r