]> git.sur5r.net Git - freertos/blob - FreeRTOS-Plus/Source/Reliance-Edge/core/driver/blockio.c
Update version of Reliance Edge.
[freertos] / FreeRTOS-Plus / Source / Reliance-Edge / core / driver / blockio.c
1 /*             ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
2
3                    Copyright (c) 2014-2015 Datalight, Inc.
4                        All Rights Reserved Worldwide.
5
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; use version 2 of the License.
9
10     This program is distributed in the hope that it will be useful,
11     but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
12     of 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 along
16     with this program; if not, write to the Free Software Foundation, Inc.,
17     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 /*  Businesses and individuals that for commercial or other reasons cannot
20     comply with the terms of the GPLv2 license may obtain a commercial license
21     before incorporating Reliance Edge into proprietary software for
22     distribution in any form.  Visit http://www.datalight.com/reliance-edge for
23     more information.
24 */
25 /** @file
26     @brief Implements block device I/O using logical blocks as the units.
27
28     The OS block device implementations operate on sectors.  The core does I/O
29     in terms of logical blocks: this module translates from logical blocks to
30     sectors.
31
32     If bBlockIoRetries is greater than 0 for the current volume, then this
33     module will retry block device calls on failure up to the configured number
34     of times.  This behavior caters to the type of unreliable hardware and
35     drivers that are sometimes found in the IoT world, where one operation may
36     fail but the next may still succeed.
37 */
38 #include <redfs.h>
39 #include <redcore.h>
40
41
42 /** @brief Read a range of logical blocks.
43
44     @param bVolNum      The volume whose block device is being read from.
45     @param ulBlockStart The first block to read.
46     @param ulBlockCount The number of blocks to read.
47     @param pBuffer      The buffer to populate with the data read.
48
49     @return A negated ::REDSTATUS code indicating the operation result.
50
51     @retval 0           Operation was successful.
52     @retval -RED_EIO    A disk I/O error occurred.
53     @retval -RED_EINVAL Invalid parameters.
54 */
55 REDSTATUS RedIoRead(
56     uint8_t     bVolNum,
57     uint32_t    ulBlockStart,
58     uint32_t    ulBlockCount,
59     void       *pBuffer)
60 {
61     REDSTATUS   ret = 0;
62
63     if(    (bVolNum >= REDCONF_VOLUME_COUNT)
64         || (ulBlockStart >= gaRedVolume[bVolNum].ulBlockCount)
65         || ((gaRedVolume[bVolNum].ulBlockCount - ulBlockStart) < ulBlockCount)
66         || (ulBlockCount == 0U)
67         || (pBuffer == NULL))
68     {
69         REDERROR();
70         ret = -RED_EINVAL;
71     }
72     else
73     {
74         uint8_t  bSectorShift = gaRedVolume[bVolNum].bBlockSectorShift;
75         uint64_t ullSectorStart = (uint64_t)ulBlockStart << bSectorShift;
76         uint32_t ulSectorCount = ulBlockCount << bSectorShift;
77         uint8_t  bRetryIdx;
78
79         REDASSERT(bSectorShift < 32U);
80         REDASSERT((ulSectorCount >> bSectorShift) == ulBlockCount);
81
82         for(bRetryIdx = 0U; bRetryIdx <= gpRedVolConf->bBlockIoRetries; bRetryIdx++)
83         {
84             ret = RedOsBDevRead(bVolNum, ullSectorStart, ulSectorCount, pBuffer);
85
86             if(ret == 0)
87             {
88                 break;
89             }
90         }
91     }
92
93     CRITICAL_ASSERT(ret == 0);
94
95     return ret;
96 }
97
98
99 #if REDCONF_READ_ONLY == 0
100 /** @brief Write a range of logical blocks.
101
102     @param bVolNum      The volume whose block device is being written to.
103     @param ulBlockStart The first block to write.
104     @param ulBlockCount The number of blocks to write.
105     @param pBuffer      The buffer containing the data to write.
106
107     @return A negated ::REDSTATUS code indicating the operation result.
108
109     @retval 0           Operation was successful.
110     @retval -RED_EIO    A disk I/O error occurred.
111     @retval -RED_EINVAL Invalid parameters.
112 */
113 REDSTATUS RedIoWrite(
114     uint8_t     bVolNum,
115     uint32_t    ulBlockStart,
116     uint32_t    ulBlockCount,
117     const void *pBuffer)
118 {
119     REDSTATUS   ret = 0;
120
121     if(    (bVolNum >= REDCONF_VOLUME_COUNT)
122         || (ulBlockStart >= gaRedVolume[bVolNum].ulBlockCount)
123         || ((gaRedVolume[bVolNum].ulBlockCount - ulBlockStart) < ulBlockCount)
124         || (ulBlockCount == 0U)
125         || (pBuffer == NULL))
126     {
127         REDERROR();
128         ret = -RED_EINVAL;
129     }
130     else
131     {
132         uint8_t  bSectorShift = gaRedVolume[bVolNum].bBlockSectorShift;
133         uint64_t ullSectorStart = (uint64_t)ulBlockStart << bSectorShift;
134         uint32_t ulSectorCount = ulBlockCount << bSectorShift;
135         uint8_t  bRetryIdx;
136
137         REDASSERT(bSectorShift < 32U);
138         REDASSERT((ulSectorCount >> bSectorShift) == ulBlockCount);
139
140         for(bRetryIdx = 0U; bRetryIdx <= gpRedVolConf->bBlockIoRetries; bRetryIdx++)
141         {
142             ret = RedOsBDevWrite(bVolNum, ullSectorStart, ulSectorCount, pBuffer);
143
144             if(ret == 0)
145             {
146                 break;
147             }
148         }
149     }
150
151     CRITICAL_ASSERT(ret == 0);
152
153     return ret;
154 }
155
156
157 /** @brief Flush any caches beneath the file system.
158
159     @param bVolNum  The volume number of the volume whose block device is being
160                     flushed.
161
162     @return A negated ::REDSTATUS code indicating the operation result.
163
164     @retval 0           Operation was successful.
165     @retval -RED_EINVAL @p bVolNum is an invalid volume number.
166     @retval -RED_EIO    A disk I/O error occurred.
167 */
168 REDSTATUS RedIoFlush(
169     uint8_t     bVolNum)
170 {
171     REDSTATUS   ret = 0;
172
173     if(bVolNum >= REDCONF_VOLUME_COUNT)
174     {
175         REDERROR();
176         ret = -RED_EINVAL;
177     }
178     else
179     {
180         uint8_t  bRetryIdx;
181
182         for(bRetryIdx = 0U; bRetryIdx <= gpRedVolConf->bBlockIoRetries; bRetryIdx++)
183         {
184             ret = RedOsBDevFlush(bVolNum);
185
186             if(ret == 0)
187             {
188                 break;
189             }
190         }
191     }
192
193     CRITICAL_ASSERT(ret == 0);
194
195     return ret;
196 }
197 #endif /* REDCONF_READ_ONLY == 0 */
198