1 /*
2  * Copyright (c) 2006-2020, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2020-08-19     lizhirui     first version
9  */
10 
11 #include <rtthread.h>
12 #include <rtdef.h>
13 #include <dfs.h>
14 #include <dfs_fs.h>
15 #include <dfs_file.h>
16 #include <ext4.h>
17 #include <ext4_debug.h>
18 #include <blk_device.h>
19 #include <stdint.h>
20 
21 static struct blk_device *blkdev;
22 static rt_uint32_t disk_sector_size;
23 
blockdev_open(struct ext4_blockdev * bdev)24 static int blockdev_open(struct ext4_blockdev *bdev)
25 {
26     int r;
27     uint32_t size;
28     rt_device_t device = (rt_device_t)blkdev;
29     struct rt_device_blk_geometry geometry;
30 
31     RT_ASSERT(device);
32 
33     r = rt_device_open((rt_device_t)blkdev, RT_DEVICE_OFLAG_RDWR);
34 
35     if (r != RT_EOK)
36     {
37         return r;
38     }
39 
40     r = rt_device_control(device, RT_DEVICE_CTRL_BLK_GETGEOME, &geometry);
41 
42     if (RT_EOK == r)
43     {
44         bdev->part_offset = 0;
45         bdev->part_size = geometry.sector_count * geometry.bytes_per_sector;
46         disk_sector_size = geometry.bytes_per_sector;
47         bdev->bdif->ph_bcnt = bdev->part_size / bdev->bdif->ph_bsize;
48     }
49 
50     return r;
51 }
52 
blockdev_bread(struct ext4_blockdev * bdev,void * buf,uint64_t blk_id,uint32_t blk_cnt)53 static int blockdev_bread(struct ext4_blockdev *bdev, void *buf, uint64_t blk_id,
54                           uint32_t blk_cnt)
55 {
56     int result;
57     rt_device_t device = (rt_device_t)blkdev;
58     struct blk_device *blk = (struct blk_device *)device;
59     RT_ASSERT(device);
60 
61     result = rt_device_read(device, blk_id * (bdev->bdif->ph_bsize / disk_sector_size),
62                             buf, blk_cnt * (bdev->bdif->ph_bsize / disk_sector_size));
63 
64     if ((blk_cnt * (bdev->bdif->ph_bsize / disk_sector_size)) == result)
65     {
66         result = 0;
67     }
68     else
69     {
70         result = -EIO;
71     }
72 
73     return result;
74 }
75 
blockdev_bwrite(struct ext4_blockdev * bdev,const void * buf,uint64_t blk_id,uint32_t blk_cnt)76 static int blockdev_bwrite(struct ext4_blockdev *bdev, const void *buf,
77                            uint64_t blk_id, uint32_t blk_cnt)
78 {
79     int result;
80     rt_device_t device = (rt_device_t)blkdev;
81 
82     RT_ASSERT(device);
83 
84     result = rt_device_write(device, blk_id * (bdev->bdif->ph_bsize / disk_sector_size),
85                              buf, blk_cnt * (bdev->bdif->ph_bsize / disk_sector_size));
86 
87     if ((blk_cnt * (bdev->bdif->ph_bsize / disk_sector_size)) == result)
88     {
89         result = 0;
90     }
91     else
92     {
93         result = -EIO;
94     }
95 
96     return result;
97 }
98 
blockdev_close(struct ext4_blockdev * bdev)99 static int blockdev_close(struct ext4_blockdev *bdev)
100 {
101     return rt_device_close((rt_device_t)blkdev);
102 }
103 
blockdev_lock(struct ext4_blockdev * bdev)104 static int blockdev_lock(struct ext4_blockdev *bdev)
105 {
106     return 0;
107 }
108 
blockdev_unlock(struct ext4_blockdev * bdev)109 static int blockdev_unlock(struct ext4_blockdev *bdev)
110 {
111     return 0;
112 }
113 
114 EXT4_BLOCKDEV_STATIC_INSTANCE(bdev, 4096, 0, blockdev_open,
115                               blockdev_bread, blockdev_bwrite, blockdev_close,
116                               blockdev_lock, blockdev_unlock);
117 
blk_device_init(struct blk_device * blk_devices)118 void blk_device_init(struct blk_device *blk_devices)
119 {
120     blkdev = blk_devices;
121 
122     if (ext4_mbr_scan(&bdev, &(blkdev->ext4_partition)) != EOK)
123     {
124         rt_kprintf("MBR scan failed!\n");
125         return;
126     }
127 }
128