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