132d7a561bd87060ca757752519039c1b0d09372
[SCSI2SD-V6.git] / src / firmware / usb_device / usbd_msc_storage_sd.c
1 //      Copyright (C) 2016 Michael McMaster <michael@codesrc.com>
2 //
3 //      This file is part of SCSI2SD.
4 //
5 //      SCSI2SD is free software: you can redistribute it and/or modify
6 //      it under the terms of the GNU General Public License as published by
7 //      the Free Software Foundation, either version 3 of the License, or
8 //      (at your option) any later version.
9 //
10 //      SCSI2SD is distributed in the hope that it will be useful,
11 //      but WITHOUT ANY WARRANTY; without even the implied warranty of
12 //      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 //      GNU General Public License for more details.
14 //
15 //      You should have received a copy of the GNU General Public License
16 //      along with SCSI2SD.  If not, see <http://www.gnu.org/licenses/>.
17
18
19 #include "usbd_msc_storage_sd.h"
20
21 #ifdef STM32F2xx
22 #include "stm32f2xx.h"
23 #endif
24
25 #ifdef STM32F4xx
26 #include "stm32f4xx.h"
27 #endif
28
29 #include "../bsp_driver_sd.h"
30 #include "../bsp.h"
31 #include "../disk.h"
32 #include "../led.h"
33 #include "../sd.h"
34 #include "../config.h"
35 #include "../geometry.h"
36 #include "../inquiry.h"
37 #include "usb_device.h"
38
39
40
41 static int8_t s2s_usbd_storage_Init(uint8_t lun);
42
43 static int8_t s2s_usbd_storage_GetCapacity(
44         uint8_t lun,
45         uint32_t *block_num,
46         uint16_t *block_size);
47
48 static int8_t s2s_usbd_storage_IsReady(uint8_t lun);
49
50 static int8_t s2s_usbd_storage_IsWriteProtected(uint8_t lun);
51
52 int8_t s2s_usbd_storage_Read(
53         uint8_t lun,
54         uint8_t *buf,
55         uint32_t blk_addr,
56         uint16_t blk_len);
57
58 int8_t s2s_usbd_storage_Write(
59         uint8_t lun,
60         uint8_t *buf,
61         uint32_t blk_addr,
62         uint16_t blk_len);
63
64 int8_t s2s_usbd_storage_GetMaxLun (void);
65 uint32_t s2s_usbd_storage_Inquiry (uint8_t lun, uint8_t* buf, uint8_t maxlen);
66
67
68 USBD_StorageTypeDef USBD_MSC_SD_fops =
69 {
70         s2s_usbd_storage_Init,
71         s2s_usbd_storage_GetCapacity,
72         s2s_usbd_storage_IsReady,
73         s2s_usbd_storage_IsWriteProtected,
74         s2s_usbd_storage_Read,
75         s2s_usbd_storage_Write,
76         s2s_usbd_storage_GetMaxLun,
77         s2s_usbd_storage_Inquiry
78 };
79
80 static const S2S_TargetCfg* getUsbConfig(uint8_t lun) {
81         int count = 0;
82         for (int i = 0; i < S2S_MAX_TARGETS; ++i)
83         {
84                 const S2S_TargetCfg* cfg = s2s_getConfigByIndex(i);
85                 if (cfg && (cfg->scsiId & S2S_CFG_TARGET_ENABLED))
86                 {
87                         if (count == lun)
88                         {
89                                 return cfg;
90                         }
91                         else
92                         {
93                                 count++;
94                         }
95                 }
96         }
97         return s2s_getConfigByIndex(0); // Fallback, try not to crash
98 }
99
100 int8_t s2s_usbd_storage_Init(uint8_t lun)
101 {
102         return (0);
103 }
104
105 int8_t s2s_usbd_storage_GetCapacity (uint8_t lun, uint32_t *block_num, uint16_t *block_size)
106 {
107         const S2S_TargetCfg* cfg = getUsbConfig(lun);
108
109         uint32_t capacity = getScsiCapacity(
110                 cfg->sdSectorStart,
111                 cfg->bytesPerSector,
112                 cfg->scsiSectors);
113
114         *block_num  = capacity;
115         *block_size = cfg->bytesPerSector;
116         return capacity ? 0 : 1;
117 }
118
119 uint32_t s2s_usbd_storage_Inquiry (uint8_t lun, uint8_t* buf, uint8_t maxlen)
120 {
121         const S2S_TargetCfg* cfg = getUsbConfig(lun);
122
123         return s2s_getStandardInquiry(cfg, buf, maxlen);
124 }
125
126 int8_t s2s_usbd_storage_IsReady (uint8_t lun)
127 {
128         const S2S_TargetCfg* cfg = getUsbConfig(lun);
129         return (
130                         cfg &&
131                         (blockDev.state & DISK_PRESENT) &&
132                         (blockDev.state & DISK_INITIALISED)
133                         ) ? 0 : 1; // inverse logic
134 }
135
136
137 int8_t s2s_usbd_storage_IsWriteProtected (uint8_t lun)
138 {
139         return blockDev.state & DISK_WP;
140 }
141
142 int8_t s2s_usbd_storage_Read (uint8_t lun,
143                 uint8_t *buf,
144                 uint32_t blk_addr,
145                 uint16_t blk_len)
146 {
147         s2s_ledOn();
148         const S2S_TargetCfg* cfg = getUsbConfig(lun);
149
150         if (cfg->bytesPerSector == 512)
151         {
152                 BSP_SD_ReadBlocks_DMA(
153                         buf,
154                         cfg->sdSectorStart + blk_addr,
155                         blk_len);
156         }
157         else
158         {
159                 int sdPerScsi = SDSectorsPerSCSISector(cfg->bytesPerSector);
160                 int sdSectorNum =  cfg->sdSectorStart + (blk_addr * sdPerScsi);
161
162                 for (int blk = 0; blk < blk_len; ++blk)
163                 {
164                         for (int i = 0; i < SDSectorsPerSCSISector(cfg->bytesPerSector); ++i)
165                         {
166                                 uint8_t partial[512] S2S_DMA_ALIGN;
167                                 BSP_SD_ReadBlocks_DMA(
168                                         partial,
169                                         sdSectorNum,
170                                         1);
171                                 sdSectorNum++;
172
173                                 int validBytes = cfg->bytesPerSector % SD_SECTOR_SIZE;
174                                 if (validBytes == 0) validBytes = SD_SECTOR_SIZE;
175
176                                 memcpy(buf, partial, validBytes);
177
178                                 buf += validBytes;
179                         }
180
181                 }
182
183         }
184         s2s_ledOff();
185         return 0;
186 }
187
188 int8_t s2s_usbd_storage_Write (uint8_t lun,
189                 uint8_t *buf,
190                 uint32_t blk_addr,
191                 uint16_t blk_len)
192 {
193         s2s_ledOn();
194         const S2S_TargetCfg* cfg = getUsbConfig(lun);
195
196         if (cfg->bytesPerSector == 512)
197         {
198                 BSP_SD_WriteBlocks_DMA(
199                         buf,
200                         cfg->sdSectorStart + blk_addr,
201                         blk_len);
202         }
203         else
204         {
205                 int sdPerScsi = SDSectorsPerSCSISector(cfg->bytesPerSector);
206                 int sdSectorNum =  cfg->sdSectorStart + (blk_addr * sdPerScsi);
207
208                 for (int blk = 0; blk < blk_len; ++blk)
209                 {
210                         for (int i = 0; i < SDSectorsPerSCSISector(cfg->bytesPerSector); ++i)
211                         {
212                                 uint8_t partial[512] S2S_DMA_ALIGN;
213                                 memcpy(partial, buf, 512);
214
215                                 BSP_SD_WriteBlocks_DMA(
216                                         partial,
217                                         sdSectorNum,
218                                         1);
219                                 sdSectorNum++;
220
221                                 int validBytes = cfg->bytesPerSector % SD_SECTOR_SIZE;
222                                 if (validBytes == 0) validBytes = SD_SECTOR_SIZE;
223
224                                 buf += validBytes;
225                         }
226
227                 }
228
229         }
230
231         s2s_ledOff();
232         return 0;
233 }
234
235 int8_t s2s_usbd_storage_GetMaxLun (void)
236 {
237         int count = 0;
238         for (int i = 0; i < S2S_MAX_TARGETS; ++i)
239         {
240                 const S2S_TargetCfg* cfg = s2s_getConfigByIndex(i);
241                 if (cfg && (cfg->scsiId & S2S_CFG_TARGET_ENABLED))
242                 {
243                         count++;
244                 }
245         }
246         return count - 1 < 0 ? 0 : count - 1;
247 }
248
249 void s2s_initUsbDeviceStorage(void)
250 {
251 #ifdef S2S_USB_FS
252         USBD_MSC_RegisterStorage(&hUsbDeviceFS, &USBD_MSC_SD_fops);
253 #endif
254 #ifdef S2S_USB_HS
255         USBD_MSC_RegisterStorage(&hUsbDeviceHS, &USBD_MSC_SD_fops);
256 #endif
257 }
258