Replace ext4_block_get with ext4_block_get_noread:
[lwext4.git] / blockdev / chibios / sdc_lwext4.c
1 /*\r
2  * Copyright (c) 2013 Grzegorz Kostka (kostka.grzegorz@gmail.com)\r
3  * All rights reserved.\r
4  *\r
5  * Redistribution and use in source and binary forms, with or without\r
6  * modification, are permitted provided that the following conditions\r
7  * are met:\r
8  *\r
9  * - Redistributions of source code must retain the above copyright\r
10  *   notice, this list of conditions and the following disclaimer.\r
11  * - Redistributions in binary form must reproduce the above copyright\r
12  *   notice, this list of conditions and the following disclaimer in the\r
13  *   documentation and/or other materials provided with the distribution.\r
14  * - The name of the author may not be used to endorse or promote products\r
15  *   derived from this software without specific prior written permission.\r
16  *\r
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\r
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\r
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\r
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\r
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\r
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\r
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
27  */\r
28 \r
29 #include "sdc_lwext4.h"\r
30 \r
31 #include <config.h>\r
32 #include <ext4_config.h>\r
33 #include <ext4_blockdev.h>\r
34 #include <ext4_errno.h>\r
35 #include <stdio.h>\r
36 #include <stdbool.h>\r
37 #include <string.h>\r
38 #include <fcntl.h>\r
39 \r
40 #include <hal.h>\r
41 #include <sdc.h>\r
42 \r
43 \r
44 /**@brief   Block size.*/\r
45 #define SDC_BLOCK_SIZE 512\r
46 \r
47 /**@brief   MBR_block ID*/\r
48 #define MBR_BLOCK_ID 0\r
49 #define MBR_PART_TABLE_OFF 446\r
50 \r
51 struct part_tab_entry {\r
52         uint8_t status;\r
53         uint8_t chs1[3];\r
54         uint8_t type;\r
55         uint8_t chs2[3];\r
56         uint32_t first_lba;\r
57         uint32_t sectors;\r
58 } __attribute__((packed));\r
59 \r
60 /**@brief   Partition block offset*/\r
61 static uint32_t part_offset;\r
62 \r
63 /**@brief IO timings*/\r
64 struct sdc_io_timings {\r
65         uint64_t acc_bread;\r
66         uint64_t acc_bwrite;\r
67 \r
68         uint32_t cnt_bread;\r
69         uint32_t cnt_bwrite;\r
70 \r
71         uint32_t av_bread;\r
72         uint32_t av_bwrite;\r
73 };\r
74 \r
75 static struct sdc_io_timings io_timings;\r
76 \r
77 void io_timings_clear(void)\r
78 {\r
79         memset(&io_timings, 0, sizeof(struct sdc_io_timings));\r
80 }\r
81 \r
82 const struct ext4_io_stats *io_timings_get(uint32_t time_sum_ms)\r
83 {\r
84         static struct ext4_io_stats s;\r
85 \r
86         s.io_read = (((float)io_timings.acc_bread * 100.0) / time_sum_ms);\r
87         s.io_read /= 1000.0;\r
88 \r
89         s.io_write = (((float)io_timings.acc_bwrite * 100.0) / time_sum_ms);\r
90         s.io_write /= 1000.0;\r
91 \r
92         s.cpu = 100.0 - s.io_read - s.io_write;\r
93 \r
94         return &s;\r
95 }\r
96 \r
97 /**********************BLOCKDEV INTERFACE**************************************/\r
98 static int sdc_open(struct ext4_blockdev *bdev);\r
99 static int sdc_bread(struct ext4_blockdev *bdev, void *buf, uint64_t blk_id,\r
100                      uint32_t blk_cnt);\r
101 static int sdc_bwrite(struct ext4_blockdev *bdev, const void *buf,\r
102                       uint64_t blk_id, uint32_t blk_cnt);\r
103 static int sdc_close(struct ext4_blockdev *bdev);\r
104 \r
105 /******************************************************************************/\r
106 EXT4_BLOCKDEV_STATIC_INSTANCE(_sdc, SDC_BLOCK_SIZE, 0, sdc_open, sdc_bread,\r
107                               sdc_bwrite, sdc_close);\r
108 \r
109 /******************************************************************************/\r
110 EXT4_BCACHE_STATIC_INSTANCE(_sdc_cache, CONFIG_BLOCK_DEV_CACHE_SIZE,\r
111                             EXT_LOGICAL_BLOCK_SIZE);\r
112 \r
113 /******************************************************************************/\r
114 \r
115 static int sdc_open(struct ext4_blockdev *bdev)\r
116 {\r
117         (void)bdev;\r
118 \r
119         static uint8_t mbr[512];\r
120         struct part_tab_entry *part0;\r
121 \r
122         sdcStart(&SDCD1, NULL);\r
123 \r
124         if (sdcConnect(&SDCD1) != HAL_SUCCESS)\r
125                 return EIO;\r
126 \r
127         if (sdcRead(&SDCD1, 0, mbr, 1) != HAL_SUCCESS)\r
128                 return EIO;\r
129 \r
130         part0 = (struct part_tab_entry *)(mbr + MBR_PART_TABLE_OFF);\r
131 \r
132         part_offset = part0->first_lba;\r
133         _sdc.ph_bcnt = SDCD1.capacity * SDC_BLOCK_SIZE;\r
134 \r
135         return EOK;\r
136 }\r
137 \r
138 static int sdc_bread(struct ext4_blockdev *bdev, void *buf, uint64_t blk_id,\r
139                      uint32_t blk_cnt)\r
140 {\r
141         (void)bdev;\r
142         bool status;\r
143         uint64_t v = tim_get_us();\r
144 \r
145         status = sdcRead(&SDCD1, blk_id, buf, blk_cnt);\r
146         if (status != HAL_SUCCESS)\r
147                 return EIO;\r
148 \r
149         io_timings.acc_bread += tim_get_us() - v;\r
150         io_timings.cnt_bread++;\r
151         io_timings.av_bread = io_timings.acc_bread / io_timings.cnt_bread;\r
152 \r
153         return EOK;\r
154 }\r
155 \r
156 static int sdc_bwrite(struct ext4_blockdev *bdev, const void *buf,\r
157                       uint64_t blk_id, uint32_t blk_cnt)\r
158 {\r
159         (void)bdev;\r
160         bool status;\r
161         uint64_t v = tim_get_us();\r
162 \r
163         status = sdcWrite(&SDCD1, blk_id, buf, blk_cnt);\r
164         if (status != HAL_SUCCESS)\r
165                 return EIO;\r
166 \r
167         io_timings.acc_bwrite += tim_get_us() - v;\r
168         io_timings.cnt_bwrite++;\r
169         io_timings.av_bwrite = io_timings.acc_bwrite / io_timings.cnt_bwrite;\r
170 \r
171         return EOK;\r
172 }\r
173 \r
174 static int sdc_close(struct ext4_blockdev *bdev)\r
175 {\r
176         (void)bdev;\r
177         return EOK;\r
178 }\r
179 \r
180 /******************************************************************************/\r
181 \r
182 struct ext4_bcache *sdc_cache_get(void) { return &_sdc_cache; }\r
183 \r
184 struct ext4_blockdev *sdc_bdev_get(void) { return &_sdc; }\r