2 * Copyright (c) 2013 Grzegorz Kostka (kostka.grzegorz@gmail.com)
\r
3 * All rights reserved.
\r
5 * Redistribution and use in source and binary forms, with or without
\r
6 * modification, are permitted provided that the following conditions
\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
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
29 #include <ext4_config.h>
\r
30 #include <ext4_blockdev.h>
\r
31 #include <ext4_errno.h>
\r
33 #include <stdbool.h>
\r
38 #include <hw_init.h>
\r
39 #include <usbh_core.h>
\r
40 #include <usbh_msc.h>
\r
42 #include <usb_msc_lwext4.h>
\r
43 #include "../../blockdev/test_lwext4.h"
\r
45 extern USBH_HandleTypeDef hUSB_Host;
\r
47 /**@brief Block size.*/
\r
48 #define USB_MSC_BLOCK_SIZE 512
\r
50 /**@brief MBR_block ID*/
\r
51 #define MBR_BLOCK_ID 0
\r
52 #define MBR_PART_TABLE_OFF 446
\r
54 struct part_tab_entry {
\r
61 }__attribute__((packed));
\r
63 /**@brief Partition block offset*/
\r
64 static uint32_t part_offset;
\r
66 /**@brief IO timings*/
\r
67 struct usb_msc_io_timings {
\r
69 uint64_t acc_bwrite;
\r
72 uint32_t cnt_bwrite;
\r
79 static struct usb_msc_io_timings io_timings;
\r
82 void io_timings_clear(void)
\r
84 memset(&io_timings, 0, sizeof(struct usb_msc_io_timings));
\r
87 const struct ext4_io_stats * io_timings_get(uint32_t time_sum_ms)
\r
89 static struct ext4_io_stats s;
\r
91 s.io_read = (((float)io_timings.acc_bread * 100.0) / time_sum_ms);
\r
92 s.io_read /= 1000.0;
\r
94 s.io_write= (((float)io_timings.acc_bwrite * 100.0) / time_sum_ms);
\r
95 s.io_write /= 1000.0;
\r
97 s.cpu = 100.0 - s.io_read - s.io_write;
\r
103 /**********************BLOCKDEV INTERFACE**************************************/
\r
104 static int usb_msc_open(struct ext4_blockdev *bdev);
\r
105 static int usb_msc_bread(struct ext4_blockdev *bdev, void *buf, uint64_t blk_id,
\r
107 static int usb_msc_bwrite(struct ext4_blockdev *bdev, const void *buf,
\r
108 uint64_t blk_id, uint32_t blk_cnt);
\r
109 static int usb_msc_close(struct ext4_blockdev *bdev);
\r
112 /******************************************************************************/
\r
113 EXT4_BLOCKDEV_STATIC_INSTANCE(
\r
115 USB_MSC_BLOCK_SIZE,
\r
123 /******************************************************************************/
\r
124 EXT4_BCACHE_STATIC_INSTANCE(_usb_msc_cache, CONFIG_BLOCK_DEV_CACHE_SIZE, EXT_LOGICAL_BLOCK_SIZE);
\r
126 /******************************************************************************/
\r
128 static int usb_msc_open(struct ext4_blockdev *bdev)
\r
132 static uint8_t mbr[512];
\r
133 struct part_tab_entry *part0;
\r
136 if(!hw_usb_connected())
\r
139 status = USBH_MSC_Read(&hUSB_Host, 0, 0, mbr, 1);
\r
140 if(status != USBH_OK)
\r
143 part0 = (struct part_tab_entry *)(mbr + MBR_PART_TABLE_OFF);
\r
145 MSC_LUNTypeDef lun;
\r
146 USBH_MSC_GetLUNInfo(&hUSB_Host, 0, &lun);
\r
148 part_offset = part0->first_lba;
\r
149 _usb_msc.ph_bcnt = lun.capacity.block_nbr;
\r
151 return hw_usb_connected() ? EOK : EIO;
\r
154 static int usb_msc_bread(struct ext4_blockdev *bdev, void *buf, uint64_t blk_id,
\r
159 uint64_t v = tim_get_us();
\r
161 if(!hw_usb_connected())
\r
164 while(!USBH_MSC_UnitIsReady(&hUSB_Host, 0))
\r
167 status = USBH_MSC_Read(&hUSB_Host, 0, blk_id + part_offset, buf, blk_cnt);
\r
168 if(status != USBH_OK)
\r
171 io_timings.acc_bread += tim_get_us() - v;
\r
172 io_timings.cnt_bread++;
\r
173 io_timings.av_bread = io_timings.acc_bread / io_timings.cnt_bread;
\r
179 static int usb_msc_bwrite(struct ext4_blockdev *bdev, const void *buf,
\r
180 uint64_t blk_id, uint32_t blk_cnt)
\r
184 uint64_t v = tim_get_us();
\r
186 if(!hw_usb_connected())
\r
189 while(!USBH_MSC_UnitIsReady(&hUSB_Host, 0))
\r
192 status = USBH_MSC_Write(&hUSB_Host, 0, blk_id + part_offset, (void *)buf, blk_cnt);
\r
193 if(status != USBH_OK)
\r
196 io_timings.acc_bwrite += tim_get_us() - v;
\r
197 io_timings.cnt_bwrite++;
\r
198 io_timings.av_bwrite = io_timings.acc_bwrite / io_timings.cnt_bwrite;
\r
203 static int usb_msc_close(struct ext4_blockdev *bdev)
\r
209 /******************************************************************************/
\r
211 struct ext4_bcache* ext4_usb_msc_cache_get(void)
\r
213 return &_usb_msc_cache;
\r
217 struct ext4_blockdev* ext4_usb_msc_get(void)
\r