+20160616 6.01
+ - Improved SD card compatibility
+ - Fixed SCSI interfaces on slower SCSI controllers
+ - Significant performance improvements
+ - Added SD card hotswap support.
+
20160528 6.0
- First BETA firmware for the 6.0 hardware version of the SCSI2SD.
/* Includes ------------------------------------------------------------------*/
#include "stm32f2xx_hal.h"
-
#ifdef HAL_SD_MODULE_ENABLED
/** @addtogroup STM32F2xx_HAL_Driver
GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11
|GPIO_PIN_12;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
+ //GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Pull = GPIO_PULLUP; // MM
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF12_SDIO;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_2;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
+ //GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Pull = GPIO_PULLUP; // MM
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF12_SDIO;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
// uint32_t Sector Number (MSB)
// Response:
// 512 bytes of data
- S2S_CMD_SD_READ
+ S2S_CMD_SD_READ,
+
+ // Command content:
+ // uint8_t S2S_CFG_DEBUG
+ // Response:
+ S2S_CMD_DEBUG,
} S2S_COMMAND;
typedef enum
\r
#include <string.h>\r
\r
-static const uint16_t FIRMWARE_VERSION = 0x0600;\r
+static const uint16_t FIRMWARE_VERSION = 0x0601;\r
\r
// 1 flash row\r
static const uint8_t DEFAULT_CONFIG[128] =\r
#endif\r
static int usbReady; // TODO MM REMOVE. Unused ?\r
\r
-static void initS2S_BoardCfg(S2S_BoardCfg* config) {\r
- if (memcmp(config->magic, "BCFG", 4)) {\r
- config->selectionDelay = 255; // auto\r
- config->flags6 = S2S_CFG_ENABLE_TERMINATOR;\r
-\r
- memcpy(\r
- s2s_cfg + sizeof(S2S_BoardCfg),\r
- DEFAULT_CONFIG,\r
- sizeof(S2S_TargetCfg));\r
- }\r
-}\r
-\r
-\r
void s2s_configInit(S2S_BoardCfg* config)\r
{\r
\r
usbReady = 0; // We don't know if host is connected yet.\r
\r
\r
- if (blockDev.state & DISK_PRESENT && sdDev.capacity)\r
+ if ((blockDev.state & DISK_PRESENT) && sdDev.capacity)\r
{\r
int cfgSectors = (S2S_CFG_SIZE + 511) / 512;\r
BSP_SD_ReadBlocks_DMA(\r
cfgSectors);\r
\r
memcpy(config, s2s_cfg, sizeof(S2S_BoardCfg));\r
- }\r
\r
- initS2S_BoardCfg(config);\r
+ if (memcmp(config->magic, "BCFG", 4))\r
+ {\r
+ // Invalid SD card config, use default.\r
+ memset(&s2s_cfg[0], 0, S2S_CFG_SIZE);\r
+ memcpy(config, s2s_cfg, sizeof(S2S_BoardCfg));\r
+ memcpy(config->magic, "BCFG", 4);\r
+ config->selectionDelay = 255; // auto\r
+ config->flags6 = S2S_CFG_ENABLE_TERMINATOR;\r
+\r
+ memcpy(\r
+ &s2s_cfg[0] + sizeof(S2S_BoardCfg),\r
+ DEFAULT_CONFIG,\r
+ sizeof(S2S_TargetCfg));\r
+ }\r
+ }\r
+ else\r
+ {\r
+ // No SD card, use existing config if valid\r
+ if (memcmp(config->magic, "BCFG", 4))\r
+ {\r
+ // Not valid, use empty config with no disks.\r
+ memset(&s2s_cfg[0], 0, S2S_CFG_SIZE);\r
+ memcpy(config, s2s_cfg, sizeof(S2S_BoardCfg));\r
+ config->selectionDelay = 255; // auto\r
+ config->flags6 = S2S_CFG_ENABLE_TERMINATOR;\r
+ }\r
+ }\r
\r
- scsiPhyConfig();\r
}\r
\r
\r
hidPacket_send(response, sizeof(response));\r
}\r
\r
+static void\r
+debugCommand()\r
+{\r
+ uint8_t response[32];\r
+ memcpy(&response, &scsiDev.cdb, 12);\r
+ response[12] = scsiDev.msgIn;\r
+ response[13] = scsiDev.msgOut;\r
+ response[14] = scsiDev.lastStatus;\r
+ response[15] = scsiDev.lastSense;\r
+ response[16] = scsiDev.phase;\r
+ response[17] = scsiStatusBSY();\r
+ response[18] = *SCSI_STS_SELECTED;\r
+ response[19] = scsiStatusATN();\r
+ response[20] = scsiStatusRST();\r
+ response[21] = scsiDev.rstCount;\r
+ response[22] = scsiDev.selCount;\r
+ response[23] = scsiDev.msgCount;\r
+ response[24] = scsiDev.cmdCount;\r
+ response[25] = scsiDev.watchdogTick;\r
+ response[26] = blockDev.state;\r
+ response[27] = scsiDev.lastSenseASC >> 8;\r
+ response[28] = scsiDev.lastSenseASC;\r
+ response[29] = *SCSI_STS_DBX;\r
+ response[30] = LastTrace;\r
+ hidPacket_send(response, sizeof(response));\r
+}\r
\r
static void\r
sdWriteCommand(const uint8_t* cmd, size_t cmdSize)\r
sdReadCommand(cmd, cmdSize);\r
break;\r
\r
+ case S2S_CMD_DEBUG:\r
+ debugCommand();\r
+ break;\r
+\r
case S2S_CMD_NONE: // invalid\r
default:\r
break;\r
int result = 0;\r
if (blockDev.state & DISK_PRESENT)\r
{\r
- result = sdInit();\r
-\r
- if (result)\r
- {\r
- blockDev.state = blockDev.state | DISK_INITIALISED;\r
- }\r
+ blockDev.state = blockDev.state | DISK_INITIALISED;\r
}\r
return result;\r
}\r
scsiWriteDMA(&scsiDev.data[SD_SECTOR_SIZE * (i % buffers)], dmaBytes);\r
scsiActive = 1;\r
}\r
-\r
}\r
\r
// We've finished transferring the data to the FPGA, now wait until it's\r
\r
const int sdPerScsi = SDSectorsPerSCSISector(bytesPerSector);\r
int totalSDSectors = transfer.blocks * sdPerScsi;\r
+ uint32_t sdLBA =\r
+ SCSISector2SD(\r
+ scsiDev.target->cfg->sdSectorStart,\r
+ bytesPerSector,\r
+ transfer.lba);\r
// int buffers = sizeof(scsiDev.data) / SD_SECTOR_SIZE;\r
// int prep = 0;\r
int i = 0;\r
uint32_t sectors =\r
totalSDSectors < maxSectors ? totalSDSectors : maxSectors;\r
scsiRead(&scsiDev.data[0], sectors * SD_SECTOR_SIZE);\r
- sdTmpWrite(&scsiDev.data[0], i + transfer.lba, sectors);\r
+ sdTmpWrite(&scsiDev.data[0], i + sdLBA, sectors);\r
i += sectors;\r
#if 0\r
// Wait for the next DMA interrupt. It's beneficial to halt the\r
\r
// Don't require the host to send us a START STOP UNIT command\r
blockDev.state = DISK_STARTED;\r
- // WP pin not available for micro-sd\r
- // TODO read card WP register\r
- #if 0\r
- if (SD_WP_Read())\r
- {\r
- blockDev.state = blockDev.state | DISK_WP;\r
- }\r
- #endif\r
}\r
\r
\r
\r
const char* Notice = "Copyright (C) 2016 Michael McMaster <michael@codesrc.com>";\r
+uint32_t lastSDPoll;\r
\r
void mainEarlyInit()\r
{\r
scsiDiskInit();\r
sdInit();\r
s2s_configInit(&scsiDev.boardCfg);\r
+ scsiPhyConfig();\r
+ scsiInit();\r
\r
s2s_debugInit();\r
\r
- scsiInit();\r
\r
MX_USB_DEVICE_Init(); // USB lun config now available.\r
\r
++delaySeconds;\r
}\r
\r
-#if 0\r
- uint32_t lastSDPoll = getTime_ms();\r
- sdCheckPresent();\r
-#endif\r
+ lastSDPoll = s2s_getTime_ms();\r
}\r
\r
void mainLoop()\r
\r
#if 0\r
sdPoll();\r
+#endif\r
\r
if (unlikely(scsiDev.phase == BUS_FREE))\r
{\r
- if (unlikely(elapsedTime_ms(lastSDPoll) > 200))\r
+ if (unlikely(s2s_elapsedTime_ms(lastSDPoll) > 200))\r
{\r
- lastSDPoll = getTime_ms();\r
- sdCheckPresent();\r
+ lastSDPoll = s2s_getTime_ms();\r
+ if (sdInit())\r
+ {\r
+ s2s_configInit(&scsiDev.boardCfg);\r
+ scsiPhyConfig();\r
+ scsiInit();\r
+\r
+\r
+ USBD_Stop(&hUsbDeviceFS);\r
+ s2s_delay_ms(128);\r
+ USBD_Start(&hUsbDeviceFS);\r
+ }\r
}\r
else\r
{\r
+#if 0\r
// Wait for our 1ms timer to save some power.\r
// There's an interrupt on the SEL signal to ensure we respond\r
// quickly to any SCSI commands. The selection abort time is\r
__WFI(); // Will wake on interrupt, regardless of mask\r
}\r
CyExitCriticalSection(interruptState);\r
+#endif\r
}\r
}\r
else if (scsiDev.phase >= 0)\r
{\r
// don't waste time scanning SD cards while we're doing disk IO\r
- lastSDPoll = getTime_ms();\r
+ lastSDPoll = s2s_getTime_ms();\r
}\r
-#endif\r
}\r
\r
// Bus settle delay + bus clear delay = 1200ns\r
s2s_delay_us(2);\r
\r
+\r
s2s_ledOff();\r
scsiDev.phase = BUS_FREE;\r
}\r
s2s_ledOff();\r
\r
scsiPhyReset();\r
- // TODO SCSI_Out_Ctl_Write(0);\r
\r
scsiDev.parityError = 0;\r
scsiDev.phase = BUS_FREE;\r
\r
void scsiInit()\r
{\r
+ static int firstInit = 1;\r
+\r
scsiDev.atnFlag = 0;\r
scsiDev.resetFlag = 1;\r
scsiDev.phase = BUS_FREE;\r
}\r
scsiDev.targets[i].reservedId = -1;\r
scsiDev.targets[i].reserverId = -1;\r
- scsiDev.targets[i].unitAttention = POWER_ON_RESET;\r
+ if (firstInit)\r
+ {\r
+ scsiDev.targets[i].unitAttention = POWER_ON_RESET;\r
+ }\r
+ else\r
+ {\r
+ scsiDev.targets[i].unitAttention = PARAMETERS_CHANGED;\r
+ }\r
scsiDev.targets[i].sense.code = NO_SENSE;\r
scsiDev.targets[i].sense.asc = NO_ADDITIONAL_SENSE_INFORMATION;\r
}\r
+ firstInit = 0;\r
}\r
\r
/* TODO REENABLE\r
#include "fpga.h"\r
#include "led.h"\r
\r
+#include <string.h>\r
+\r
// Private DMA variables.\r
static int dmaInProgress = 0;\r
\r
scsiTxDMAComplete = 1; // TODO not used much\r
scsiRxDMAComplete = 0; // TODO not used much\r
\r
- HAL_DMA_Start(&fsmcToMem, (uint32_t) SCSI_FIFO_DATA, (uint32_t) data, count); // TODO MM count/4 for tx\r
+ HAL_DMA_Start(&fsmcToMem, (uint32_t) SCSI_FIFO_DATA, (uint32_t) data, count);\r
}\r
\r
int\r
}\r
#endif\r
\r
+ // FPGA comms test code\r
+ #ifdef FPGA_TEST\r
+\r
+ while(1)\r
+ {\r
+ for (int j = 0; j < SCSI_FIFO_DEPTH; ++j)\r
+ {\r
+ scsiDev.data[j] = j;\r
+ }\r
+\r
+ *SCSI_CTRL_PHASE = DATA_IN;\r
+ HAL_DMA_Start(\r
+ &memToFSMC,\r
+ (uint32_t) &scsiDev.data[0],\r
+ (uint32_t) SCSI_FIFO_DATA,\r
+ SCSI_FIFO_DEPTH / 4);\r
+\r
+ HAL_DMA_PollForTransfer(\r
+ &memToFSMC,\r
+ HAL_DMA_FULL_TRANSFER,\r
+ 0xffffffff);\r
+\r
+ memset(&scsiDev.data[0], 0, SCSI_FIFO_DEPTH);\r
+\r
+ *SCSI_CTRL_PHASE = DATA_OUT;\r
+ HAL_DMA_Start(\r
+ &fsmcToMem,\r
+ (uint32_t) SCSI_FIFO_DATA,\r
+ (uint32_t) &scsiDev.data[0],\r
+ SCSI_FIFO_DEPTH);\r
+\r
+ HAL_DMA_PollForTransfer(\r
+ &fsmcToMem,\r
+ HAL_DMA_FULL_TRANSFER,\r
+ 0xffffffff);\r
+\r
+ for (int j = 0; j < SCSI_FIFO_DEPTH; ++j)\r
+ {\r
+ if (scsiDev.data[j] != (uint8_t) j)\r
+ {\r
+ while (1)\r
+ {\r
+ s2s_ledOn();\r
+ s2s_delay_ms(100);\r
+ s2s_ledOff();\r
+ s2s_delay_ms(100);\r
+ }\r
+ }\r
+ }\r
+\r
+ s2s_fpgaReset();\r
+\r
+ }\r
+ #endif\r
+\r
}\r
\r
static void scsiPhyInitDMA()\r
#define SCSI_STS_FIFO_COMPLETE ((volatile uint8_t*)0x60000012)
#define SCSI_STS_SELECTED ((volatile uint8_t*)0x60000013)
#define SCSI_STS_SCSI ((volatile uint8_t*)0x60000014)
+#define SCSI_STS_DBX ((volatile uint8_t*)0x60000015)
#define SCSI_FIFO_DATA ((volatile uint8_t*)0x60000020)
#define SCSI_FIFO_DEPTH 512
-#define scsiPhyFifoFull() ((*SCSI_STS_FIFO & 0x02) == 0x02)
-#define scsiPhyFifoEmpty() ((*SCSI_STS_FIFO & 0x01) == 0x01)
+#define scsiPhyFifoFull() ((*SCSI_STS_FIFO & 0x01) == 0x01)
+#define scsiPhyFifoEmpty() ((*SCSI_STS_FIFO & 0x02) == 0x02)
#define scsiPhyFifoFlip() \
{\
*SCSI_FIFO_SEL = scsiPhyFifoSel; \
}
-// Clear 4 byte fifo
-#define scsiPhyFifoClear() (void) scsiPhyRx(); (void) scsiPhyRx(); (void) scsiPhyRx(); (void) scsiPhyRx();
-
#define scsiPhyTx(val) *SCSI_FIFO_DATA = (val)
#define scsiPhyRx() *SCSI_FIFO_DATA
#define scsiPhyComplete() ((*SCSI_STS_FIFO_COMPLETE & 0x01) == 0x01)
{\r
init = 1;\r
\r
- //TODO MM SEE STUPID SD_DMA_RxCplt that require the SD IRQs to preempt\r
-// Configured with 4 bits preemption, NO sub priority.\r
- HAL_NVIC_SetPriority(DMA2_Stream3_IRQn, 8, 0);\r
- HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn);\r
- HAL_NVIC_SetPriority(DMA2_Stream6_IRQn, 8, 0);\r
- HAL_NVIC_EnableIRQ(DMA2_Stream6_IRQn);\r
-#if 0\r
- sdDMATxChan =\r
- SD_TX_DMA_DmaInitialize(\r
- 2, // Bytes per burst\r
- 1, // request per burst\r
- HI16(CYDEV_SRAM_BASE),\r
- HI16(CYDEV_PERIPH_BASE)\r
- );\r
-\r
- sdDMARxChan =\r
- SD_RX_DMA_DmaInitialize(\r
- 1, // Bytes per burst\r
- 1, // request per burst\r
- HI16(CYDEV_PERIPH_BASE),\r
- HI16(CYDEV_SRAM_BASE)\r
- );\r
-\r
- CyDmaChDisable(sdDMATxChan);\r
- CyDmaChDisable(sdDMARxChan);\r
-\r
- SD_RX_DMA_COMPLETE_StartEx(sdRxISR);\r
- SD_TX_DMA_COMPLETE_StartEx(sdTxISR);\r
-#endif\r
+ //TODO MM SEE STUPID SD_DMA_RxCplt that require the SD IRQs to preempt\r
+ // Configured with 4 bits preemption, NO sub priority.\r
+ HAL_NVIC_SetPriority(DMA2_Stream3_IRQn, 8, 0);\r
+ HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn);\r
+ HAL_NVIC_SetPriority(DMA2_Stream6_IRQn, 8, 0);\r
+ HAL_NVIC_EnableIRQ(DMA2_Stream6_IRQn);\r
}\r
}\r
\r
BSP_SD_WriteBlocks_DMA((uint32_t*) data, lba * 512ll, 512, sectors);\r
}\r
\r
-int sdInit()\r
+static void sdClear()\r
{\r
- int result = 0;\r
- //int i;\r
-\r
- // TODO sdCmdState = CMD_STATE_IDLE;\r
sdDev.version = 0;\r
sdDev.ccs = 0;\r
sdDev.capacity = 0;\r
memset(sdDev.csd, 0, sizeof(sdDev.csd));\r
memset(sdDev.cid, 0, sizeof(sdDev.cid));\r
+}\r
\r
-// TODO should be in POLL method!\r
-\r
- sdInitDMA();\r
-#if 0\r
-\r
- SD_CS_SetDriveMode(SD_CS_DM_STRONG);\r
- SD_CS_Write(1); // Set CS inactive (active low)\r
-\r
- // Set the SPI clock for 400kHz transfers\r
- // 25MHz / 400kHz approx factor of 63.\r
- // The register contains (divider - 1)\r
- uint16_t clkDiv25MHz = SD_Data_Clk_GetDividerRegister();\r
- SD_Data_Clk_SetDivider(((clkDiv25MHz + 1) * 63) - 1);\r
- // Wait for the clock to settle.\r
- CyDelayUs(1);\r
-\r
- SDCard_Start(); // Enable SPI hardware\r
-\r
- // Power on sequence. 74 clock cycles of a "1" while CS unasserted.\r
- for (i = 0; i < 10; ++i)\r
- {\r
- sdSpiByte(0xFF);\r
- }\r
-\r
- SD_CS_Write(0); // Set CS active (active low)\r
- CyDelayUs(1);\r
-\r
- sdSpiByte(0xFF);\r
- v = sdDoCommand(SD_GO_IDLE_STATE, 0, 1, 0);\r
- if(v != 1){goto bad;}\r
-\r
- ledOn();\r
- if (!sendIfCond()) goto bad; // Sets V1 or V2 flag CMD8\r
- if (!sdOpCond()) goto bad; // ACMD41. Wait for init completes.\r
- if (!sdReadOCR()) goto bad; // CMD58. Get CCS flag. Only valid after init.\r
-\r
- // This command will be ignored if sdDev.ccs is set.\r
- // SDHC and SDXC are always 512bytes.\r
- v = sdCRCCommandAndResponse(SD_SET_BLOCKLEN, SD_SECTOR_SIZE); //Force sector size\r
- if(v){goto bad;}\r
- v = sdCRCCommandAndResponse(SD_CRC_ON_OFF, 0); //crc off\r
- if(v){goto bad;}\r
-\r
- // now set the sd card back to full speed.\r
- // The SD Card spec says we can run SPI @ 25MHz\r
- SDCard_Stop();\r
-\r
- // We can't run at full-speed with the pullup resistors enabled.\r
- SD_MISO_SetDriveMode(SD_MISO_DM_DIG_HIZ);\r
- SD_MOSI_SetDriveMode(SD_MOSI_DM_STRONG);\r
- SD_SCK_SetDriveMode(SD_SCK_DM_STRONG);\r
-\r
- SD_Data_Clk_SetDivider(clkDiv25MHz);\r
- CyDelayUs(1);\r
- SDCard_Start();\r
-\r
- // Clear out rubbish data through clock change\r
- CyDelayUs(1);\r
- SDCard_ReadRxStatus();\r
- SDCard_ReadTxStatus();\r
- SDCard_ClearFIFO();\r
-\r
- if (!sdReadCSD()) goto bad;\r
- sdReadCID();\r
-\r
- result = 1;\r
- goto out;\r
+static int sdDoInit()\r
+{\r
+ int result = 0;\r
\r
-bad:\r
- SD_Data_Clk_SetDivider(clkDiv25MHz); // Restore the clock for our next retry\r
- sdDev.capacity = 0;\r
+ // TODO sdCmdState = CMD_STATE_IDLE;\r
+ sdClear();\r
\r
-out:\r
- sdClearStatus();\r
- ledOff();\r
- return result;\r
\r
-#endif\r
- uint8_t error = BSP_SD_Init();\r
+ int8_t error = BSP_SD_Init();\r
if (error == MSD_OK)\r
{\r
memcpy(sdDev.csd, &SDCardInfo.SD_csd, sizeof(sdDev.csd));\r
}\r
}\r
\r
-void sdCheckPresent()\r
+#endif\r
+int sdInit()\r
{\r
// Check if there's an SD card present.\r
+ int result = 0;\r
+\r
+#if 0\r
if ((scsiDev.phase == BUS_FREE) &&\r
(sdIOState == SD_IDLE) &&\r
(sdCmdState == CMD_STATE_IDLE))\r
+#endif\r
+ static int firstInit = 1;\r
+\r
+ if (firstInit)\r
{\r
- // The CS line is pulled high by the SD card.\r
- // De-assert the line, and check if it's high.\r
- // This isn't foolproof as it'll be left floating without\r
- // an SD card. We can't use the built-in pull-down resistor as it will\r
- // overpower the SD pullup resistor.\r
- SD_CS_Write(0);\r
- SD_CS_SetDriveMode(SD_CS_DM_DIG_HIZ);\r
-\r
- // Delay extended to work with 60cm cables running cards at 2.85V\r
- CyDelayCycles(128);\r
- uint8_t cs = SD_CS_Read();\r
- SD_CS_SetDriveMode(SD_CS_DM_STRONG) ;\r
+ blockDev.state &= ~(DISK_PRESENT | DISK_INITIALISED);\r
+ sdClear();\r
+ sdInitDMA();\r
+ }\r
+\r
+ if (scsiDev.phase == BUS_FREE)\r
+ {\r
+ uint8_t cs = HAL_GPIO_ReadPin(nSD_CD_GPIO_Port, nSD_CD_Pin) ? 0 : 1;\r
+ uint8_t wp = HAL_GPIO_ReadPin(nSD_WP_GPIO_Port, nSD_WP_Pin) ? 0 : 1;\r
\r
if (cs && !(blockDev.state & DISK_PRESENT))\r
{\r
- static int firstInit = 1;\r
+ s2s_ledOn();\r
\r
// Debounce\r
- CyDelay(250);\r
+ if (!firstInit)\r
+ {\r
+ s2s_delay_ms(250);\r
+ }\r
\r
- if (sdInit())\r
+ if (sdDoInit())\r
{\r
blockDev.state |= DISK_PRESENT | DISK_INITIALISED;\r
\r
+ if (wp)\r
+ {\r
+ blockDev.state |= DISK_WP;\r
+ }\r
+ else\r
+ {\r
+ blockDev.state &= ~DISK_WP;\r
+ }\r
+\r
// Always "start" the device. Many systems (eg. Apple System 7)\r
// won't respond properly to\r
// LOGICAL_UNIT_NOT_READY_INITIALIZING_COMMAND_REQUIRED sense\r
// START STOP UNIT command.\r
blockDev.state |= DISK_STARTED;\r
\r
- if (!firstInit)\r
+ result = 1;\r
+\r
+ s2s_ledOff();\r
+ }\r
+ else\r
+ {\r
+ for (int i = 0; i < 10; ++i)\r
{\r
- int i;\r
- for (i = 0; i < MAX_SCSI_TARGETS; ++i)\r
- {\r
- scsiDev.targets[i].unitAttention = PARAMETERS_CHANGED;\r
- }\r
+ // visual indicator of SD error\r
+ s2s_ledOff();\r
+ s2s_delay_ms(50);\r
+ s2s_ledOn();\r
+ s2s_delay_ms(50);\r
}\r
- firstInit = 0;\r
+ s2s_ledOff();\r
}\r
}\r
else if (!cs && (blockDev.state & DISK_PRESENT))\r
blockDev.state &= ~DISK_PRESENT;\r
blockDev.state &= ~DISK_INITIALISED;\r
int i;\r
- for (i = 0; i < MAX_SCSI_TARGETS; ++i)\r
+ for (i = 0; i < S2S_MAX_TARGETS; ++i)\r
{\r
scsiDev.targets[i].unitAttention = PARAMETERS_CHANGED;\r
}\r
+\r
+ HAL_SD_DeInit(&hsd);\r
}\r
}\r
+ firstInit = 0;\r
+\r
+ return result;\r
}\r
\r
-#endif\r
int sdReadSectorDMAPoll();
void sdCompleteTransfer(void);
-void sdCheckPresent();
void sdPoll();
#endif
#include "stm32f2xx.h"
#include "bsp_driver_sd.h"
#include "../bsp.h"
+#include "../disk.h"
#include "../led.h"
#include "../sd.h"
#include "../config.h"
return s2s_getStandardInquiry(cfg, buf, maxlen);
}
-int8_t s2s_usbd_storage_IsReady (uint8_t lun)
+int8_t s2s_usbd_storage_IsReady (uint8_t lun)
{
- return (0);
+ const S2S_TargetCfg* cfg = getUsbConfig(lun);
+ return (
+ cfg &&
+ (blockDev.state & DISK_PRESENT) &&
+ (blockDev.state & DISK_INITIALISED)
+ ) ? 0 : 1; // inverse logic
}
int8_t s2s_usbd_storage_IsWriteProtected (uint8_t lun)
{
- return 0;
+ return blockDev.state & DISK_WP;
}
int8_t s2s_usbd_storage_Read (uint8_t lun,