SD hotswap, SD fixes, SCSI interface fixes, performance improvements. v6.0BETA2
authorMichael McMaster <michael@codesrc.com>
Thu, 16 Jun 2016 11:21:00 +0000 (21:21 +1000)
committerMichael McMaster <michael@codesrc.com>
Thu, 16 Jun 2016 11:21:00 +0000 (21:21 +1000)
15 files changed:
CHANGELOG
STM32CubeMX/SCSI2SD-V6/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_hal_sd.c
STM32CubeMX/SCSI2SD-V6/Src/sdio.c
doc/SCSI2SD_QuickStartGuide.odt
include/scsi2sd.h
rtl/fpga_bitmap.o
src/firmware/config.c
src/firmware/disk.c
src/firmware/main.c
src/firmware/scsi.c
src/firmware/scsiPhy.c
src/firmware/scsiPhy.h
src/firmware/sd.c
src/firmware/sd.h
src/firmware/usb_device/usbd_msc_storage_sd.c

index 284852018592837ce24527bd1fc3f96ec86647ba..03414da6786b2b3f839cdea73375f726d02f8028 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,2 +1,8 @@
+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.
index 399b7de64beea61442c0f141ff02293f7e981187..418163e46710aaea8c9ba9f59dc210f566b27b74 100755 (executable)
 
 /* Includes ------------------------------------------------------------------*/
 #include "stm32f2xx_hal.h"
-
 #ifdef HAL_SD_MODULE_ENABLED
 
 /** @addtogroup STM32F2xx_HAL_Driver
index 49b4de96d10d1fcd86aa7483c683a0c21c97d425..d1bb9dcae93a5336e463a9c1a1f5c9a85374e7ba 100755 (executable)
@@ -84,14 +84,16 @@ void HAL_SD_MspInit(SD_HandleTypeDef* hsd)
     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);
index 61b1bba2ebd5497379380f716828464d3b3010ee..9dbcb0ffed04bf579e06e2dd170d94c68fa25ce8 100644 (file)
Binary files a/doc/SCSI2SD_QuickStartGuide.odt and b/doc/SCSI2SD_QuickStartGuide.odt differ
index cee3be070d7855a3391978dc23e6211e95cf4c49..a59fd38da17edcaf2fe7d627e482d53cf2ca7b64 100755 (executable)
@@ -192,7 +192,12 @@ typedef enum
        // 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
index 55c02c0eb511181ceeb1962e0a6532f345f16e25..16130841bb44c71ff8a517f31a57d295dd13d880 100644 (file)
Binary files a/rtl/fpga_bitmap.o and b/rtl/fpga_bitmap.o differ
index 1015ae3445cdcfbcad25987177f7a12c152b2ab5..a19087d82df3fe6a21980a8a640a60fd1c843027 100755 (executable)
@@ -38,7 +38,7 @@
 \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
@@ -68,19 +68,6 @@ static int usbDebugEpState;
 #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
@@ -88,7 +75,7 @@ void s2s_configInit(S2S_BoardCfg* config)
        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
@@ -98,11 +85,35 @@ void s2s_configInit(S2S_BoardCfg* config)
                        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
@@ -154,6 +165,32 @@ scsiDevInfoCommand()
        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
@@ -230,6 +267,10 @@ processCommand(const uint8_t* cmd, size_t cmdSize)
                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
index 886bfe254600bba37661fc73e8f02a472db09ba9..d4c826b76815083319d799ed72ff4ee04f14246c 100755 (executable)
@@ -35,12 +35,7 @@ static int doSdInit()
        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
@@ -628,7 +623,6 @@ void scsiDiskPoll()
                                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
@@ -656,6 +650,11 @@ void scsiDiskPoll()
 \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
@@ -677,7 +676,7 @@ void scsiDiskPoll()
                        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
@@ -863,13 +862,5 @@ void scsiDiskInit()
 \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
index 04d2c3b0c3382248a4e274fa40f014d22f4b281f..a2317626cfe783e123c2a2f698aa99e5dba11292 100755 (executable)
@@ -32,6 +32,7 @@
 \r
 \r
 const char* Notice = "Copyright (C) 2016 Michael McMaster <michael@codesrc.com>";\r
+uint32_t lastSDPoll;\r
 \r
 void mainEarlyInit()\r
 {\r
@@ -51,10 +52,11 @@ void mainInit()
        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
@@ -72,10 +74,7 @@ void mainInit()
                ++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
@@ -89,16 +88,28 @@ void mainLoop()
 \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
@@ -110,13 +121,13 @@ void mainLoop()
                                __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
index 297a1bd889c1d1d85a242558fc3430a319a1de01..c4b53a572d9c33249079f65b3baa4f3cbe9063a7 100755 (executable)
@@ -70,6 +70,7 @@ static void enter_BusFree()
        // Bus settle delay + bus clear delay = 1200ns\r
        s2s_delay_us(2);\r
 \r
+\r
        s2s_ledOff();\r
        scsiDev.phase = BUS_FREE;\r
 }\r
@@ -459,7 +460,6 @@ static void scsiReset()
        s2s_ledOff();\r
 \r
        scsiPhyReset();\r
-       // TODO SCSI_Out_Ctl_Write(0);\r
 \r
        scsiDev.parityError = 0;\r
        scsiDev.phase = BUS_FREE;\r
@@ -896,6 +896,8 @@ void scsiPoll(void)
 \r
 void scsiInit()\r
 {\r
+       static int firstInit = 1;\r
+\r
        scsiDev.atnFlag = 0;\r
        scsiDev.resetFlag = 1;\r
        scsiDev.phase = BUS_FREE;\r
@@ -920,10 +922,18 @@ void scsiInit()
                }\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
index bdaef5890ddc68848d3494d98a389aaeb0d804d1..1a8a6aea0585d33580d0a1593cd2e2627e9391be 100755 (executable)
@@ -26,6 +26,8 @@
 #include "fpga.h"\r
 #include "led.h"\r
 \r
+#include <string.h>\r
+\r
 // Private DMA variables.\r
 static int dmaInProgress = 0;\r
 \r
@@ -133,7 +135,7 @@ scsiReadDMA(uint8_t* data, uint32_t count)
        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
@@ -424,6 +426,61 @@ void scsiPhyReset()
        }\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
index dff2f345456bd3b86943c369d2e7ca60772b80ef..6c72e4151b017fbaccc93a367ae03ad97b8443f7 100755 (executable)
 #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() \
 {\
@@ -44,9 +45,6 @@
        *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)
index 08d6a195312afac5525e6f5b0ad263d0c5357bf6..8f0d50342d3a1b646a2fb15090fbe738ce434e17 100755 (executable)
@@ -787,35 +787,12 @@ static void sdInitDMA()
        {\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
@@ -829,97 +806,24 @@ void sdTmpWrite(uint8_t* data, uint32_t lba, int sectors)
        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
@@ -1019,37 +923,54 @@ void sdPoll()
        }\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
@@ -1057,15 +978,21 @@ void sdCheckPresent()
                                // 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
@@ -1074,12 +1001,16 @@ void sdCheckPresent()
                        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
index 878d9f0680e6d1058ffeb6905d70791979853e5d..bb8c0574775aa8a562cf7d221e80b11c03255fb8 100755 (executable)
@@ -82,7 +82,6 @@ void sdReadSingleSectorDMA(uint32_t lba, uint8_t* outputBuffer);
 int sdReadSectorDMAPoll();
 
 void sdCompleteTransfer(void);
-void sdCheckPresent();
 void sdPoll();
 
 #endif
index db6e411b1e9cb0e4a6b6074c1b988d54bf883f44..3cb44873728ea5feaeca071d60c1c3598fe41d95 100755 (executable)
@@ -20,6 +20,7 @@
 #include "stm32f2xx.h"
 #include "bsp_driver_sd.h"
 #include "../bsp.h"
+#include "../disk.h"
 #include "../led.h"
 #include "../sd.h"
 #include "../config.h"
@@ -114,15 +115,20 @@ uint32_t s2s_usbd_storage_Inquiry (uint8_t lun, uint8_t* buf, uint8_t maxlen)
        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,