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;
31 __block_mount_partitions(struct hba_device* hd_dev);
34 __block_register(struct block_dev* dev);
40 lbd_pile = cake_new_pile("block_dev", sizeof(struct block_dev), 1, 0);
41 dev_registry = vcalloc(sizeof(struct block_dev*), MAX_DEV);
43 blk_sysroot = twifs_dir_node(NULL, "block");
47 __block_read(struct device* dev, void* buf, size_t offset, size_t len)
50 struct block_dev* bdev = (struct block_dev*)dev->underlay;
51 size_t bsize = bdev->blk_size, rd_block = offset / bsize + bdev->start_lba,
52 r = offset % bsize, rd_size = 0;
54 if (!(len = MIN(len, ((size_t)bdev->end_lba - rd_block + 1) * bsize))) {
58 struct vecbuf* vbuf = vbuf_alloc(NULL, buf, len);
59 struct blkio_req* req;
63 tmp_buf = vzalloc(bsize);
64 rd_size = MIN(len, bsize - r);
65 vbuf->buf.size = bsize;
66 vbuf->buf.buffer = tmp_buf;
68 if ((len - rd_size)) {
69 vbuf_alloc(vbuf, buf + rd_size, len - rd_size);
73 req = blkio_vrd(vbuf, rd_block, NULL, NULL, 0);
74 blkio_commit(bdev->blkio, req);
78 // XXX temporary work-around
79 // in case pwait used in proc0. Need a dummy process!
80 wait_if((req->flags & BLKIO_PENDING));
82 if (!(errno = req->errcode)) {
83 memcpy(buf, tmp_buf + r, rd_size);
99 __block_write(struct device* dev, void* buf, size_t offset, size_t len)
101 struct block_dev* bdev = (struct block_dev*)dev->underlay;
102 size_t bsize = bdev->blk_size, rd_block = offset / bsize + bdev->start_lba,
105 if (!(len = MIN(len, ((size_t)bdev->end_lba - rd_block + 1) * bsize))) {
109 struct vecbuf* vbuf = vbuf_alloc(NULL, buf, len);
110 struct blkio_req* req;
111 void* tmp_buf = NULL;
114 size_t rd_size = MIN(len, bsize - r);
115 tmp_buf = vzalloc(bsize);
116 vbuf->buf.size = bsize;
117 vbuf->buf.buffer = tmp_buf;
119 memcpy(tmp_buf + r, buf, rd_size);
120 vbuf_alloc(vbuf, buf + rd_size, len - rd_size);
123 req = blkio_vwr(vbuf, rd_block, NULL, NULL, 0);
124 blkio_commit(bdev->blkio, req);
128 // XXX temporary work-around
129 // in case pwait used in proc0. Need a dummy process!
130 wait_if((req->flags & BLKIO_PENDING));
132 int errno = req->errcode;
149 block_alloc_dev(const char* blk_id, void* driver, req_handler ioreq_handler)
151 struct block_dev* bdev = cake_grab(lbd_pile);
152 memset(bdev, 0, sizeof(struct block_dev));
153 llist_init_head(&bdev->parts);
154 strncpy(bdev->name, blk_id, PARTITION_NAME_SIZE);
156 bdev->blkio = blkio_newctx(ioreq_handler);
157 bdev->driver = driver;
158 bdev->blkio->driver = driver;
164 block_mount(struct block_dev* bdev, devfs_exporter fs_export)
168 if (!__block_register(bdev)) {
173 errno = blkpart_probegpt(bdev->dev);
175 kprintf(KERROR "Corrupted partition table. (%d)", errno);
177 // TODO try other PT parser...
180 struct twifs_node* dev_root = twifs_dir_node(blk_sysroot, bdev->bdev_id);
181 blk_set_blkmapping(bdev, dev_root);
182 fs_export(bdev, dev_root);
187 kprintf(KERROR "Fail to mount block device: %s (%x)\n", bdev->name, -errno);
192 __block_register(struct block_dev* bdev)
194 if (free_slot >= MAX_DEV) {
198 struct device* dev = device_addvol(NULL, bdev, "sd%c", 'a' + free_slot);
199 dev->write = __block_write;
200 dev->read = __block_read;
203 strcpy(bdev->bdev_id, dev->name_val);
204 dev_registry[free_slot++] = bdev;
209 blk_mount_part(struct block_dev* bdev,
215 struct block_dev* pbdev = cake_grab(lbd_pile);
216 memcpy(pbdev, bdev, sizeof(*bdev));
219 device_addvol(NULL, pbdev, "%sp%d", bdev->bdev_id, index + 1);
220 dev->write = __block_write;
221 dev->read = __block_read;
223 pbdev->start_lba = start_lba;
224 pbdev->end_lba = end_lba;
227 strcpy(pbdev->bdev_id, dev->name_val);
229 strncpy(pbdev->name, name, PARTITION_NAME_SIZE);
232 llist_append(&bdev->parts, &pbdev->parts);