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 * 512ll, 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 sdCompleteTransfer()
\r
96 static void sdInitDMA()
\r
98 // One-time init only.
\r
99 static uint8_t init = 0;
\r
104 //TODO MM SEE STUPID SD_DMA_RxCplt that require the SD IRQs to preempt
\r
105 // Ie. priority must be geater than the SDIO_IRQn priority.
\r
106 // 4 bits preemption, NO sub priority.
\r
107 HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
\r
108 HAL_NVIC_SetPriority(DMA2_Stream3_IRQn, 8, 0);
\r
109 HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn);
\r
110 HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
\r
111 HAL_NVIC_SetPriority(DMA2_Stream6_IRQn, 8, 0);
\r
112 HAL_NVIC_EnableIRQ(DMA2_Stream6_IRQn);
\r
116 static void sdClear()
\r
119 sdDev.capacity = 0;
\r
120 memset(sdDev.csd, 0, sizeof(sdDev.csd));
\r
121 memset(sdDev.cid, 0, sizeof(sdDev.cid));
\r
124 static int sdDoInit()
\r
130 int8_t error = BSP_SD_Init();
\r
131 if (error == MSD_OK)
\r
133 HAL_SD_CardInfoTypeDef cardInfo;
\r
134 HAL_SD_GetCardInfo(&hsd, &cardInfo);
\r
135 memcpy(sdDev.csd, hsd.CSD, sizeof(sdDev.csd));
\r
136 memcpy(sdDev.cid, hsd.CID, sizeof(sdDev.cid));
\r
137 sdDev.capacity = cardInfo.BlockNbr;
\r
138 blockDev.state |= DISK_PRESENT | DISK_INITIALISED;
\r
145 blockDev.state &= ~(DISK_PRESENT | DISK_INITIALISED);
\r
147 sdDev.capacity = 0;
\r
156 // Check if there's an SD card present.
\r
159 static int firstInit = 1;
\r
163 blockDev.state &= ~(DISK_PRESENT | DISK_INITIALISED);
\r
168 if (firstInit || (scsiDev.phase == BUS_FREE))
\r
170 uint8_t cs = HAL_GPIO_ReadPin(nSD_CD_GPIO_Port, nSD_CD_Pin) ? 0 : 1;
\r
171 uint8_t wp = HAL_GPIO_ReadPin(nSD_WP_GPIO_Port, nSD_WP_Pin) ? 0 : 1;
\r
173 if (cs && !(blockDev.state & DISK_PRESENT))
\r
185 blockDev.state |= DISK_PRESENT | DISK_INITIALISED;
\r
189 blockDev.state |= DISK_WP;
\r
193 blockDev.state &= ~DISK_WP;
\r
196 // Always "start" the device. Many systems (eg. Apple System 7)
\r
197 // won't respond properly to
\r
198 // LOGICAL_UNIT_NOT_READY_INITIALIZING_COMMAND_REQUIRED sense
\r
199 // code, even if they stopped it first with
\r
200 // START STOP UNIT command.
\r
201 blockDev.state |= DISK_STARTED;
\r
209 for (int i = 0; i < 10; ++i)
\r
211 // visual indicator of SD error
\r
220 else if (!cs && (blockDev.state & DISK_PRESENT))
\r
222 sdDev.capacity = 0;
\r
223 blockDev.state &= ~DISK_PRESENT;
\r
224 blockDev.state &= ~DISK_INITIALISED;
\r
226 for (i = 0; i < S2S_MAX_TARGETS; ++i)
\r
228 scsiDev.targets[i].unitAttention = PARAMETERS_CHANGED;
\r
231 HAL_SD_DeInit(&hsd);
\r