1 // Copyright (C) 2013 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
19 #include "stm32f2xx.h"
\r
23 #include "stm32f4xx.h"
\r
27 #include "bsp_driver_sd.h"
\r
37 #include "scsiPhy.h"
\r
44 static int sdCmdActive = 0;
\r
47 sdReadDMAPoll(uint32_t remainingSectors)
\r
49 // TODO DMA byte counting disabled for now as it's not
\r
51 // We can ask the SDIO controller how many bytes have been
\r
52 // processed (SDIO_GetDataCounter()) but I'm not sure if that
\r
53 // means the data has been transfered via dma to memory yet.
\r
54 // uint32_t dmaBytesRemaining = __HAL_DMA_GET_COUNTER(hsd.hdmarx) * 4;
\r
56 if (HAL_SD_GetState(&hsd) != HAL_SD_STATE_BUSY)
\r
58 // DMA transfer is complete
\r
60 return remainingSectors;
\r
64 return remainingSectors - ((dmaBytesRemaining + (SD_SECTOR_SIZE - 1)) / SD_SECTOR_SIZE);
\r
69 void sdReadDMA(uint32_t lba, uint32_t sectors, uint8_t* outputBuffer)
\r
71 if (HAL_SD_ReadBlocks_DMA(&hsd, outputBuffer, lba, sectors) != HAL_OK)
\r
75 scsiDev.status = CHECK_CONDITION;
\r
76 scsiDev.target->sense.code = HARDWARE_ERROR;
\r
77 scsiDev.target->sense.asc = LOGICAL_UNIT_COMMUNICATION_FAILURE;
\r
78 scsiDev.phase = STATUS;
\r
86 void sdReadCmd(uint32_t lba, uint32_t sectors)
\r
88 uint32_t errorstate;
\r
89 hsd.ErrorCode = HAL_SD_ERROR_NONE;
\r
90 hsd.State = HAL_SD_STATE_BUSY;
\r
92 /* Initialize data control register */
\r
93 hsd.Instance->DCTRL = 0U;
\r
95 // The IRQ handler clears flags which we need to read the fifo data
\r
96 #if defined(SDIO_STA_STBITERR)
\r
97 __HAL_SD_DISABLE_IT(&hsd, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_RXOVERR | SDIO_IT_DATAEND | SDIO_FLAG_RXFIFOHF | SDIO_IT_STBITERR));
\r
99 __HAL_SD_DISABLE_IT(&hsd, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_RXOVERR | SDIO_IT_DATAEND | SDIO_FLAG_RXFIFOHF));
\r
102 if(hsd.SdCard.CardType != CARD_SDHC_SDXC)
\r
106 errorstate = SDMMC_CmdBlockLength(hsd.Instance, 512u);
\r
107 if(errorstate != HAL_SD_ERROR_NONE)
\r
109 __HAL_SD_CLEAR_FLAG(&hsd, SDIO_STATIC_FLAGS);
\r
112 scsiDev.status = CHECK_CONDITION;
\r
113 scsiDev.target->sense.code = HARDWARE_ERROR;
\r
114 scsiDev.target->sense.asc = LOGICAL_UNIT_COMMUNICATION_FAILURE;
\r
115 scsiDev.phase = STATUS;
\r
122 hsd.Context = SD_CONTEXT_READ_MULTIPLE_BLOCK;
\r
123 errorstate = SDMMC_CmdReadMultiBlock(hsd.Instance, lba);
\r
127 hsd.Context = SD_CONTEXT_READ_SINGLE_BLOCK;
\r
128 errorstate = SDMMC_CmdReadSingleBlock(hsd.Instance, lba);
\r
131 if(errorstate != HAL_SD_ERROR_NONE)
\r
133 __HAL_SD_CLEAR_FLAG(&hsd, SDIO_STATIC_FLAGS);
\r
137 scsiDev.status = CHECK_CONDITION;
\r
138 scsiDev.target->sense.code = HARDWARE_ERROR;
\r
139 scsiDev.target->sense.asc = LOGICAL_UNIT_COMMUNICATION_FAILURE;
\r
140 scsiDev.phase = STATUS;
\r
148 void sdReadPIOData(uint32_t sectors)
\r
150 /* Initialize data control register */
\r
151 hsd.Instance->DCTRL = 0U;
\r
153 SDIO_DataInitTypeDef config;
\r
154 config.DataTimeOut = SDMMC_DATATIMEOUT;
\r
155 config.DataLength = sectors * 512u;
\r
156 config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B;
\r
157 config.TransferDir = SDIO_TRANSFER_DIR_TO_SDIO;
\r
158 config.TransferMode = SDIO_TRANSFER_MODE_BLOCK;
\r
159 config.DPSM = SDIO_DPSM_ENABLE;
\r
160 SDIO_ConfigData(hsd.Instance, &config);
\r
164 void sdCompleteTransfer()
\r
168 HAL_SD_Abort(&hsd);
\r
173 static void sdClear()
\r
176 sdDev.capacity = 0;
\r
177 memset(sdDev.csd, 0, sizeof(sdDev.csd));
\r
178 memset(sdDev.cid, 0, sizeof(sdDev.cid));
\r
181 static int sdDoInit()
\r
187 int8_t error = BSP_SD_Init();
\r
188 if (error == MSD_OK)
\r
190 HAL_SD_CardInfoTypeDef cardInfo;
\r
191 HAL_SD_GetCardInfo(&hsd, &cardInfo);
\r
192 memcpy(sdDev.csd, hsd.CSD, sizeof(sdDev.csd));
\r
193 memcpy(sdDev.cid, hsd.CID, sizeof(sdDev.cid));
\r
194 sdDev.capacity = cardInfo.LogBlockNbr;
\r
195 blockDev.state |= DISK_PRESENT | DISK_INITIALISED;
\r
202 blockDev.state &= ~(DISK_PRESENT | DISK_INITIALISED);
\r
204 sdDev.capacity = 0;
\r
213 // Check if there's an SD card present.
\r
216 static int firstInit = 1;
\r
220 blockDev.state &= ~(DISK_PRESENT | DISK_INITIALISED);
\r
224 if (firstInit || (scsiDev.phase == BUS_FREE))
\r
226 uint8_t cs = HAL_GPIO_ReadPin(nSD_CD_GPIO_Port, nSD_CD_Pin) ? 0 : 1;
\r
228 if (cs && !(blockDev.state & DISK_PRESENT))
\r
232 // Debounce. Quicker if the card is present at
\r
236 for (int i = 0; cs && (i < 50); ++i)
\r
238 cs = HAL_GPIO_ReadPin(nSD_CD_GPIO_Port, nSD_CD_Pin) ? 0 : 1;
\r
243 if (cs && sdDoInit())
\r
245 blockDev.state |= DISK_PRESENT | DISK_INITIALISED;
\r
247 uint8_t wp = HAL_GPIO_ReadPin(nSD_WP_GPIO_Port, nSD_WP_Pin) ? 0 : 1;
\r
250 blockDev.state |= DISK_WP;
\r
254 blockDev.state &= ~DISK_WP;
\r
263 for (int i = 0; i < 10; ++i)
\r
265 // visual indicator of SD error
\r
278 else if (!cs && (blockDev.state & DISK_PRESENT))
\r
280 sdDev.capacity = 0;
\r
281 blockDev.state &= ~DISK_PRESENT;
\r
282 blockDev.state &= ~DISK_INITIALISED;
\r
284 for (i = 0; i < S2S_MAX_TARGETS; ++i)
\r
286 scsiDev.targets[i].unitAttention = PARAMETERS_CHANGED;
\r
289 HAL_SD_DeInit(&hsd);
\r
297 // Return 1 if the SD card has no buffer space left for writes and/or is
\r
298 // in the programming state.
\r
301 // Busy while DAT0 is held low.
\r
302 return HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_8) == 0;
\r
307 if (blockDev.state & DISK_PRESENT)
\r
309 /*HAL_SD_CardStateTypeDef cardState = */HAL_SD_GetCardState(&hsd);
\r