1 // Copyright (C) 2014 Michael McMaster <michael@codesrc.com>
\r
3 // This file is part of SCSI2SD.
\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
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
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
23 #include "scsiPhy.h"
\r
27 #include "bootloader.h"
\r
30 #include "../../include/scsi2sd.h"
\r
31 #include "../../include/hidpacket.h"
\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
41 static const uint16_t FIRMWARE_VERSION = 0x0600;
\r
44 static const uint8_t DEFAULT_CONFIG[128] =
\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
55 static uint8_t s2s_cfg[S2S_CFG_SIZE] S2S_DMA_ALIGN;
\r
65 static int usbInEpState;
\r
67 static int usbDebugEpState;
\r
69 static int usbReady; // TODO MM REMOVE. Unused ?
\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
77 s2s_cfg + sizeof(S2S_BoardCfg),
\r
79 sizeof(S2S_TargetCfg));
\r
84 void s2s_configInit(S2S_BoardCfg* config)
\r
87 usbInEpState = USB_IDLE;
\r
88 usbReady = 0; // We don't know if host is connected yet.
\r
91 if (blockDev.state & DISK_PRESENT && sdDev.capacity)
\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
100 memcpy(config, s2s_cfg, sizeof(S2S_BoardCfg));
\r
103 initS2S_BoardCfg(config);
\r
112 uint8_t response[] =
\r
114 S2S_CFG_STATUS_GOOD
\r
116 hidPacket_send(response, sizeof(response));
\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
126 hidPacket_send(response, sizeof(response));
\r
133 int resultCode = 0; // TODO scsiSelfTest();
\r
134 uint8_t response[] =
\r
136 resultCode == 0 ? S2S_CFG_STATUS_GOOD : S2S_CFG_STATUS_ERR,
\r
139 hidPacket_send(response, sizeof(response));
\r
143 scsiDevInfoCommand()
\r
145 uint8_t response[] =
\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
154 hidPacket_send(response, sizeof(response));
\r
159 sdWriteCommand(const uint8_t* cmd, size_t cmdSize)
\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
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
176 uint8_t response[] =
\r
178 S2S_CFG_STATUS_GOOD
\r
180 hidPacket_send(response, sizeof(response));
\r
184 sdReadCommand(const uint8_t* cmd, size_t cmdSize)
\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
196 BSP_SD_ReadBlocks_DMA((uint32_t*) cmd, lba * 512ll, 512, 1);
\r
197 hidPacket_send(cmd, 512);
\r
201 processCommand(const uint8_t* cmd, size_t cmdSize)
\r
209 case S2S_CMD_REBOOT:
\r
210 s2s_enterBootloader();
\r
213 case S2S_CMD_SDINFO:
\r
217 case S2S_CMD_SCSITEST:
\r
221 case S2S_CMD_DEVINFO:
\r
222 scsiDevInfoCommand();
\r
225 case S2S_CMD_SD_WRITE:
\r
226 sdWriteCommand(cmd, cmdSize);
\r
229 case S2S_CMD_SD_READ:
\r
230 sdReadCommand(cmd, cmdSize);
\r
233 case S2S_CMD_NONE: // invalid
\r
239 void s2s_configPoll()
\r
241 if (!USBD_Composite_IsConfigured(&hUsbDeviceFS))
\r
243 usbInEpState = USB_IDLE;
\r
247 if (USBD_HID_IsReportReady(&hUsbDeviceFS))
\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
257 const uint8_t* cmd = hidPacket_getPacket(&cmdSize);
\r
258 if (cmd && (cmdSize > 0))
\r
260 processCommand(cmd, cmdSize);
\r
266 switch (usbInEpState)
\r
270 uint8_t hidBuffer[USBHID_LEN];
\r
271 const uint8_t* nextChunk = hidPacket_getHIDBytes(hidBuffer);
\r
275 USBD_HID_SendReport (&hUsbDeviceFS, nextChunk, sizeof(hidBuffer));
\r
276 usbInEpState = USB_DATA_SENT;
\r
281 case USB_DATA_SENT:
\r
282 if (!USBD_HID_IsBusy(&hUsbDeviceFS))
\r
285 usbInEpState = USB_IDLE;
\r
300 if(USBFS_GetEPState(USB_EP_COMMAND) == USBFS_OUT_BUFFER_FULL)
\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
306 if (byteCount >= 1 &&
\r
307 hidBuffer[0] == 0x01)
\r
310 Bootloadable_1_Load();
\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
318 switch (usbDebugEpState)
\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
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
347 hidBuffer[62] = FIRMWARE_VERSION >> 8;
\r
348 hidBuffer[63] = FIRMWARE_VERSION;
\r
350 USBFS_LoadInEP(USB_EP_DEBUG, (uint8 *)&hidBuffer, sizeof(hidBuffer));
\r
351 usbDebugEpState = USB_DATA_SENT;
\r
354 case USB_DATA_SENT:
\r
355 if (USBFS_bGetEPAckState(USB_EP_DEBUG))
\r
358 usbDebugEpState = USB_IDLE;
\r
366 CY_ISR(debugTimerISR)
\r
368 Debug_Timer_ReadStatusRegister();
\r
369 Debug_Timer_Interrupt_ClearPending();
\r
370 uint8 savedIntrStatus = CyEnterCriticalSection();
\r
372 CyExitCriticalSection(savedIntrStatus);
\r
376 void s2s_debugInit()
\r
379 Debug_Timer_Interrupt_StartEx(debugTimerISR);
\r
380 Debug_Timer_Start();
\r
387 Debug_Timer_Stop();
\r
394 Debug_Timer_Start();
\r
398 int isDebugEnabled()
\r
403 // Public method for storing MODE SELECT results.
\r
404 void s2s_configSave(int scsiId, uint16_t bytesPerSector)
\r
406 S2S_TargetCfg* cfg = (S2S_TargetCfg*) s2s_getConfigById(scsiId);
\r
407 cfg->bytesPerSector = bytesPerSector;
\r
409 BSP_SD_WriteBlocks_DMA(
\r
410 (uint32_t*) &s2s_cfg[0],
\r
411 (sdDev.capacity - S2S_CFG_SIZE) * 512ll,
\r
413 (S2S_CFG_SIZE + 511) / 512);
\r
417 const S2S_TargetCfg* s2s_getConfigByIndex(int i)
\r
419 return (const S2S_TargetCfg*)
\r
420 (s2s_cfg + sizeof(S2S_BoardCfg) + (i * sizeof(S2S_TargetCfg)));
\r
423 const S2S_TargetCfg* s2s_getConfigById(int scsiId)
\r
426 for (i = 0; i < S2S_MAX_TARGETS; ++i)
\r
428 const S2S_TargetCfg* tgt = s2s_getConfigByIndex(i);
\r
429 if ((tgt->scsiId & S2S_CFG_TARGET_ID_BITS) == scsiId)
\r