1 #include <hal/ahci/hba.h>
2 #include <klibc/stdio.h>
3 #include <klibc/string.h>
5 #include <lunaix/block.h>
6 #include <lunaix/fs/twifs.h>
7 #include <lunaix/mm/cake.h>
8 #include <lunaix/mm/valloc.h>
9 #include <lunaix/syslog.h>
11 #include <lunaix/blkpart_gpt.h>
13 #include <lunaix/spike.h>
24 static struct cake_pile* lbd_pile;
25 static struct block_dev** dev_registry;
26 static struct twifs_node* blk_sysroot;
27 static struct device* blk_parent_dev;
32 __block_mount_partitions(struct hba_device* hd_dev);
35 __block_register(struct block_dev* dev);
41 lbd_pile = cake_new_pile("block_dev", sizeof(struct block_dev), 1, 0);
42 dev_registry = vcalloc(sizeof(struct block_dev*), MAX_DEV);
44 blk_sysroot = twifs_dir_node(NULL, "block");
45 blk_parent_dev = device_addcat(NULL, "block");
49 __block_read(struct device* dev, void* buf, size_t offset, size_t len)
52 struct block_dev* bdev = (struct block_dev*)dev->underlay;
53 size_t bsize = bdev->blk_size, rd_block = offset / bsize + bdev->start_lba,
54 r = offset % bsize, rd_size = 0;
56 if (!(len = MIN(len, ((size_t)bdev->end_lba - rd_block + 1) * bsize))) {
60 struct vecbuf* vbuf = NULL;
61 struct blkio_req* req;
62 void *head_buf = NULL, *tail_buf = NULL;
65 if (r || len < bsize) {
66 head_buf = valloc(bsize);
67 rd_size = MIN(len, bsize - r);
68 vbuf_alloc(&vbuf, head_buf, bsize);
72 if ((len - rd_size)) {
73 size_t llen = len - rd_size;
74 assert_msg(!(llen % bsize), "misalign block read");
75 vbuf_alloc(&vbuf, buf + rd_size, llen);
78 req = blkio_vrd(vbuf, rd_block, NULL, NULL, 0);
79 blkio_commit(bdev->blkio, req, BLKIO_WAIT);
81 if (!(errno = req->errcode)) {
82 memcpy(buf, head_buf + r, rd_size);
98 __block_write(struct device* dev, void* buf, size_t offset, size_t len)
100 struct block_dev* bdev = (struct block_dev*)dev->underlay;
101 size_t bsize = bdev->blk_size, wr_block = offset / bsize + bdev->start_lba,
102 r = offset % bsize, wr_size = 0;
104 if (!(len = MIN(len, ((size_t)bdev->end_lba - wr_block + 1) * bsize))) {
108 struct vecbuf* vbuf = NULL;
109 struct blkio_req* req;
110 void* tmp_buf = NULL;
113 size_t wr_size = MIN(len, bsize - r);
114 tmp_buf = vzalloc(bsize);
115 vbuf_alloc(&vbuf, tmp_buf, bsize);
117 memcpy(tmp_buf + r, buf, wr_size);
120 if ((len - wr_size)) {
121 size_t llen = len - wr_size;
122 assert_msg(!(llen % bsize), "misalign block write");
123 vbuf_alloc(&vbuf, buf + wr_size, llen);
126 req = blkio_vwr(vbuf, wr_block, NULL, NULL, 0);
127 blkio_commit(bdev->blkio, req, BLKIO_WAIT);
129 int errno = req->errcode;
146 __block_read_page(struct device* dev, void* buf, size_t offset)
148 struct vecbuf* vbuf = NULL;
149 struct block_dev* bdev = (struct block_dev*)dev->underlay;
151 u32_t lba = offset / bdev->blk_size + bdev->start_lba;
152 u32_t rd_lba = MIN(lba + PG_SIZE / bdev->blk_size, bdev->end_lba);
160 vbuf_alloc(&vbuf, buf, rd_lba * bdev->blk_size);
162 struct blkio_req* req = blkio_vrd(vbuf, lba, NULL, NULL, 0);
164 blkio_commit(bdev->blkio, req, BLKIO_WAIT);
166 int errno = req->errcode;
168 errno = rd_lba * bdev->blk_size;
179 __block_write_page(struct device* dev, void* buf, size_t offset)
181 struct vecbuf* vbuf = NULL;
182 struct block_dev* bdev = (struct block_dev*)dev->underlay;
184 u32_t lba = offset / bdev->blk_size + bdev->start_lba;
185 u32_t rd_lba = MIN(lba + PG_SIZE / bdev->blk_size, bdev->end_lba);
193 vbuf_alloc(&vbuf, buf, rd_lba * bdev->blk_size);
195 struct blkio_req* req = blkio_vwr(vbuf, lba, NULL, NULL, 0);
197 blkio_commit(bdev->blkio, req, BLKIO_WAIT);
199 int errno = req->errcode;
201 errno = rd_lba * bdev->blk_size;
212 __block_rd_lb(struct block_dev* bdev, void* buf, u64_t start, size_t count)
214 struct vecbuf* vbuf = NULL;
215 vbuf_alloc(&vbuf, buf, bdev->blk_size * count);
217 struct blkio_req* req = blkio_vrd(vbuf, start, NULL, NULL, 0);
218 blkio_commit(bdev->blkio, req, BLKIO_WAIT);
220 int errno = req->errcode;
234 __block_wr_lb(struct block_dev* bdev, void* buf, u64_t start, size_t count)
236 struct vecbuf* vbuf = NULL;
237 vbuf_alloc(&vbuf, buf, bdev->blk_size * count);
239 struct blkio_req* req = blkio_vwr(vbuf, start, NULL, NULL, 0);
240 blkio_commit(bdev->blkio, req, BLKIO_WAIT);
242 int errno = req->errcode;
256 block_alloc_buf(struct block_dev* bdev)
258 return valloc(bdev->blk_size);
262 block_free_buf(struct block_dev* bdev, void* buf)
268 block_alloc_dev(const char* blk_id, void* driver, req_handler ioreq_handler)
270 struct block_dev* bdev = cake_grab(lbd_pile);
271 memset(bdev, 0, sizeof(struct block_dev));
272 llist_init_head(&bdev->parts);
273 strncpy(bdev->name, blk_id, PARTITION_NAME_SIZE);
275 bdev->blkio = blkio_newctx(ioreq_handler);
276 bdev->driver = driver;
277 bdev->blkio->driver = driver;
278 bdev->ops = (struct block_dev_ops){ .block_read = __block_rd_lb,
279 .block_write = __block_wr_lb };
285 block_mount(struct block_dev* bdev, devfs_exporter fs_export)
289 if (!__block_register(bdev)) {
294 errno = blkpart_probegpt(bdev->dev);
296 kprintf(KERROR "Fail to parse partition table (%d)\n", errno);
298 // TODO try other PT parser...
301 struct twifs_node* dev_root = twifs_dir_node(blk_sysroot, bdev->bdev_id);
302 blk_set_blkmapping(bdev, dev_root);
303 fs_export(bdev, dev_root);
308 kprintf(KERROR "Fail to mount block device: %s (%x)\n", bdev->name, -errno);
313 __block_register(struct block_dev* bdev)
315 if (free_slot >= MAX_DEV) {
320 device_addvol(blk_parent_dev, bdev, "sd%c", 'a' + free_slot);
321 dev->write = __block_write;
322 dev->write_page = __block_write_page;
323 dev->read = __block_read;
324 dev->read_page = __block_read_page;
327 strcpy(bdev->bdev_id, dev->name_val);
328 dev_registry[free_slot++] = bdev;
333 blk_mount_part(struct block_dev* bdev,
339 struct block_dev* pbdev = cake_grab(lbd_pile);
340 memcpy(pbdev, bdev, sizeof(*bdev));
343 device_addvol(NULL, pbdev, "%sp%d", bdev->bdev_id, index + 1);
344 dev->write = __block_write;
345 dev->write_page = __block_write_page;
346 dev->read = __block_read;
347 dev->read_page = __block_read_page;
349 pbdev->start_lba = start_lba;
350 pbdev->end_lba = end_lba;
353 strcpy(pbdev->bdev_id, dev->name_val);
355 strncpy(pbdev->name, name, PARTITION_NAME_SIZE);
358 llist_append(&bdev->parts, &pbdev->parts);