1 // Copyright (C) 2014 Michael McMaster <michael@codesrc.com>
3 // This file is part of SCSI2SD.
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.
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.
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/>.
26 #include "bootloader.h"
29 #include "../../include/scsi2sd.h"
30 #include "../../include/hidpacket.h"
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"
40 static const uint16_t FIRMWARE_VERSION
= 0x0607;
43 static const uint8_t DEFAULT_CONFIG
[128] =
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
54 static uint8_t s2s_cfg
[S2S_CFG_SIZE
] S2S_DMA_ALIGN
;
64 static int usbInEpState
;
66 static int usbDebugEpState
;
68 static int usbReady
; // TODO MM REMOVE. Unused ?
70 void s2s_configInit(S2S_BoardCfg
* config
)
73 usbInEpState
= USB_IDLE
;
74 usbReady
= 0; // We don't know if host is connected yet.
77 if ((blockDev
.state
& DISK_PRESENT
) && sdDev
.capacity
)
79 int cfgSectors
= (S2S_CFG_SIZE
+ 511) / 512;
80 BSP_SD_ReadBlocks_DMA(
81 (uint32_t*) &s2s_cfg
[0],
82 (sdDev
.capacity
- cfgSectors
) * 512ll,
86 memcpy(config
, s2s_cfg
, sizeof(S2S_BoardCfg
));
88 if (memcmp(config
->magic
, "BCFG", 4))
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
;
98 &s2s_cfg
[0] + sizeof(S2S_BoardCfg
),
100 sizeof(S2S_TargetCfg
));
105 // No SD card, use existing config if valid
106 if (memcmp(config
->magic
, "BCFG", 4))
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
;
126 hidPacket_send(response
, sizeof(response
));
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
));
136 hidPacket_send(response
, sizeof(response
));
143 int resultCode
= scsiSelfTest();
146 resultCode
== 0 ? S2S_CFG_STATUS_GOOD
: S2S_CFG_STATUS_ERR
,
149 hidPacket_send(response
, sizeof(response
));
157 FIRMWARE_VERSION
>> 8,
158 FIRMWARE_VERSION
& 0xff,
159 sdDev
.capacity
>> 24,
160 sdDev
.capacity
>> 16,
164 hidPacket_send(response
, sizeof(response
));
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
));
196 sdWriteCommand(const uint8_t* cmd
, size_t cmdSize
)
203 (((uint32_t)cmd
[1]) << 24) |
204 (((uint32_t)cmd
[2]) << 16) |
205 (((uint32_t)cmd
[3]) << 8) |
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);
217 hidPacket_send(response
, sizeof(response
));
221 sdReadCommand(const uint8_t* cmd
, size_t cmdSize
)
228 (((uint32_t)cmd
[1]) << 24) |
229 (((uint32_t)cmd
[2]) << 16) |
230 (((uint32_t)cmd
[3]) << 8) |
233 BSP_SD_ReadBlocks_DMA((uint32_t*) cmd
, lba
* 512ll, 512, 1);
234 hidPacket_send(cmd
, 512);
238 processCommand(const uint8_t* cmd
, size_t cmdSize
)
247 s2s_enterBootloader();
254 case S2S_CMD_SCSITEST
:
258 case S2S_CMD_DEVINFO
:
259 scsiDevInfoCommand();
262 case S2S_CMD_SD_WRITE
:
263 sdWriteCommand(cmd
, cmdSize
);
266 case S2S_CMD_SD_READ
:
267 sdReadCommand(cmd
, cmdSize
);
274 case S2S_CMD_NONE
: // invalid
280 void s2s_configPoll()
282 if (!USBD_Composite_IsConfigured(&hUsbDeviceFS
))
284 usbInEpState
= USB_IDLE
;
288 if (USBD_HID_IsReportReady(&hUsbDeviceFS
))
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
);
298 const uint8_t* cmd
= hidPacket_getPacket(&cmdSize
);
299 if (cmd
&& (cmdSize
> 0))
301 processCommand(cmd
, cmdSize
);
307 switch (usbInEpState
)
311 uint8_t hidBuffer
[USBHID_LEN
];
312 const uint8_t* nextChunk
= hidPacket_getHIDBytes(hidBuffer
);
316 USBD_HID_SendReport (&hUsbDeviceFS
, nextChunk
, sizeof(hidBuffer
));
317 usbInEpState
= USB_DATA_SENT
;
323 if (!USBD_HID_IsBusy(&hUsbDeviceFS
))
326 usbInEpState
= USB_IDLE
;
335 // Public method for storing MODE SELECT results.
336 void s2s_configSave(int scsiId
, uint16_t bytesPerSector
)
338 S2S_TargetCfg
* cfg
= (S2S_TargetCfg
*) s2s_getConfigById(scsiId
);
339 cfg
->bytesPerSector
= bytesPerSector
;
341 BSP_SD_WriteBlocks_DMA(
342 (uint32_t*) &s2s_cfg
[0],
343 (sdDev
.capacity
- S2S_CFG_SIZE
) * 512ll,
345 (S2S_CFG_SIZE
+ 511) / 512);
349 const S2S_TargetCfg
* s2s_getConfigByIndex(int i
)
351 return (const S2S_TargetCfg
*)
352 (s2s_cfg
+ sizeof(S2S_BoardCfg
) + (i
* sizeof(S2S_TargetCfg
)));
355 const S2S_TargetCfg
* s2s_getConfigById(int scsiId
)
358 for (i
= 0; i
< S2S_MAX_TARGETS
; ++i
)
360 const S2S_TargetCfg
* tgt
= s2s_getConfigByIndex(i
);
361 if ((tgt
->scsiId
& S2S_CFG_TARGET_ID_BITS
) == scsiId
)