1 /*
2 * Copyright (c) 2009 Travis Geiselbrecht
3 *
4 * Use of this source code is governed by a MIT-style
5 * license that can be found in the LICENSE file or at
6 * https://opensource.org/licenses/MIT
7 */
8 #pragma once
9
10 #include <assert.h>
11 #include <sys/types.h>
12 #include <lk/list.h>
13
14 __BEGIN_CDECLS
15
16 #define BIO_FLAGS_NONE (0 << 0)
17 #define BIO_FLAG_CACHE_ALIGNED_READS (1 << 0)
18 #define BIO_FLAG_CACHE_ALIGNED_WRITES (1 << 1)
19
20 typedef uint32_t bnum_t;
21
22 typedef struct bio_erase_geometry_info {
23 off_t start; // start of the region in bytes.
24 off_t size;
25 size_t erase_size;
26 size_t erase_shift;
27 } bio_erase_geometry_info_t;
28
29 typedef struct bdev {
30 struct list_node node;
31 volatile int ref;
32
33 /* info about the block device */
34 char *name;
35 off_t total_size;
36
37 size_t block_size;
38 size_t block_shift;
39 bnum_t block_count;
40
41 size_t geometry_count;
42 const bio_erase_geometry_info_t *geometry;
43
44 uint8_t erase_byte;
45
46 uint32_t flags;
47
48 /* function pointers */
49 ssize_t (*read)(struct bdev *, void *buf, off_t offset, size_t len);
50 ssize_t (*read_block)(struct bdev *, void *buf, bnum_t block, uint count);
51 ssize_t (*write)(struct bdev *, const void *buf, off_t offset, size_t len);
52 ssize_t (*write_block)(struct bdev *, const void *buf, bnum_t block, uint count);
53 ssize_t (*erase)(struct bdev *, off_t offset, size_t len);
54 int (*ioctl)(struct bdev *, int request, void *argp);
55 void (*close)(struct bdev *);
56 } bdev_t;
57
58 /* user api */
59 bdev_t *bio_open(const char *name);
60 void bio_close(bdev_t *dev);
61 ssize_t bio_read(bdev_t *dev, void *buf, off_t offset, size_t len);
62 ssize_t bio_read_block(bdev_t *dev, void *buf, bnum_t block, uint count);
63 ssize_t bio_write(bdev_t *dev, const void *buf, off_t offset, size_t len);
64 ssize_t bio_write_block(bdev_t *dev, const void *buf, bnum_t block, uint count);
65 ssize_t bio_erase(bdev_t *dev, off_t offset, size_t len);
66 int bio_ioctl(bdev_t *dev, int request, void *argp);
67
68 /* register a block device */
69 void bio_register_device(bdev_t *dev);
70 void bio_unregister_device(bdev_t *dev);
71
72 /* used during bdev construction */
73 void bio_initialize_bdev(bdev_t *dev,
74 const char *name,
75 size_t block_size,
76 bnum_t block_count,
77 size_t geometry_count,
78 const bio_erase_geometry_info_t *geometry,
79 const uint32_t flags);
80
81 /* debug stuff */
82 void bio_dump_devices(void);
83
84 /* subdevice support */
85 status_t bio_publish_subdevice(const char *parent_dev,
86 const char *subdev,
87 bnum_t startblock,
88 bnum_t block_count);
89
90 /* memory based block device */
91 int create_membdev(const char *name, void *ptr, size_t len);
92
93 /* helper routine to trim an offset + len to the device */
94 size_t bio_trim_range(const bdev_t *dev, off_t offset, size_t len);
95
96 /* helper routine to trim to a block range in the device */
97 uint bio_trim_block_range(const bdev_t *dev, bnum_t block, uint count);
98
99 /* utility routine */
bio_does_overlap(uint64_t start1,uint64_t len1,uint64_t start2,uint64_t len2)100 static inline bool bio_does_overlap(uint64_t start1, uint64_t len1,
101 uint64_t start2, uint64_t len2) {
102 uint64_t end1 = start1 + len1;
103 uint64_t end2 = start2 + len2;
104
105 DEBUG_ASSERT(end1 >= start1);
106 DEBUG_ASSERT(end2 >= start2);
107
108 return (((start1 >= start2) && (start1 < end2)) ||
109 ((start2 >= start1) && (start2 < end1)));
110 }
111
bio_contains_range(uint64_t container_start,uint64_t container_len,uint64_t contained_start,uint64_t contained_len)112 static inline bool bio_contains_range(uint64_t container_start, uint64_t container_len,
113 uint64_t contained_start, uint64_t contained_len) {
114 uint64_t container_end = container_start + container_len;
115 uint64_t contained_end = contained_start + contained_len;
116
117 DEBUG_ASSERT(container_end >= container_start);
118 DEBUG_ASSERT(contained_end >= contained_start);
119
120 return ((container_start <= contained_start) &&
121 (container_end >= contained_end));
122 }
123
124 /* generic bio ioctls */
125 enum bio_ioctl_num {
126 BIO_IOCTL_NULL = 0,
127 BIO_IOCTL_GET_MEM_MAP, /* if supported, request a pointer to the memory map of the device */
128 BIO_IOCTL_PUT_MEM_MAP, /* if needed, return the pointer (to 'close' the map) */
129 BIO_IOCTL_GET_MAP_ADDR, /* if supported, request a pointer to the memory map without putting the device into linear mode */
130 BIO_IOCTL_IS_MAPPED, /* if supported, returns whether or not the device is memory mapped. */
131 };
132
133 __END_CDECLS