+ free_slot = 0;
+}
+
+int
+__block_read(struct v_file* file, void* buffer, size_t len);
+
+int
+__block_write(struct v_file* file, void* buffer, size_t len);
+
+void
+block_twifs_create()
+{
+ struct twifs_node* dev = twifs_toplevel_node("dev", 3);
+ struct twifs_node* dev_block = twifs_dir_node(dev, "block", 5);
+
+ if (!dev_block) {
+ kprintf(KERROR "fail to create twifs node");
+ return;
+ }
+
+ struct block_dev* bdev;
+ struct twifs_node* bdev_node;
+ for (size_t i = 0; i < MAX_DEV; i++) {
+ if (!(bdev = dev_registry[i])) {
+ continue;
+ }
+
+ bdev_node =
+ twifs_dir_node(dev_block, bdev->bdev_id, strlen(bdev->bdev_id));
+ bdev_node->fops.read = __block_read;
+ bdev_node->fops.write = __block_write;
+ bdev_node->data = i;
+ bdev_node->inode->fsize = bdev->hd_dev->max_lba;
+ }
+}
+
+int
+__block_read(struct v_file* file, void* buffer, size_t len)
+{
+ int index = (int)((struct twifs_node*)file->inode->data)->data;
+ int errno;
+ struct block_dev* bdev;
+ if (index < 0 || index >= MAX_DEV || !(bdev = dev_registry[index])) {
+ return ENXIO;
+ }
+ size_t acc_size = 0, rd_size = 0, bsize = bdev->hd_dev->block_size,
+ rd_block = 0;
+ void* block = valloc(bsize);
+
+ while (acc_size < len) {
+ if (!bdev->hd_dev->ops.read_buffer(
+ bdev->hd_dev, file->f_pos + rd_block, block, bsize)) {
+ errno = ENXIO;
+ goto error;
+ }
+ rd_size = MIN(len - acc_size, bsize);
+ memcpy(buffer + acc_size, block, rd_size);
+ acc_size += rd_size;
+ rd_block++;
+ }
+
+ vfree(block);
+ return rd_block;
+
+error:
+ vfree(block);
+ return errno;
+}
+
+int
+__block_write(struct v_file* file, void* buffer, size_t len)
+{
+ int index = (int)((struct twifs_node*)file->inode->data)->data;
+ int errno;
+ struct block_dev* bdev;
+ if (index < 0 || index >= MAX_DEV || !(bdev = dev_registry[index])) {
+ return ENXIO;
+ }
+ size_t acc_size = 0, wr_size = 0, bsize = bdev->hd_dev->block_size,
+ wr_block = 0;
+ void* block = valloc(bsize);
+
+ while (acc_size < len) {
+ wr_size = MIN(len - acc_size, bsize);
+ memcpy(block, buffer + acc_size, wr_size);
+ if (!bdev->hd_dev->ops.write_buffer(
+ bdev->hd_dev, file->f_pos + wr_block, block, bsize)) {
+ errno = ENXIO;
+ break;
+ }
+ acc_size += wr_size;
+ wr_block++;
+ }
+
+ vfree(block);
+ return wr_block;
+
+error:
+ vfree(block);
+ return errno;