feat: simple device abstraction layer
[lunaix-os.git] / lunaix-os / kernel / block.c
index 0e28f666e2d03548a756e00ecc63e4b05b89bcb7..a4c1942b7756e2632900efb83e69c5a2295590b4 100644 (file)
@@ -1,11 +1,15 @@
 #include <hal/ahci/hba.h>
+#include <klibc/stdio.h>
 #include <klibc/string.h>
 #include <lib/crc.h>
 #include <lunaix/block.h>
+#include <lunaix/fs/twifs.h>
 #include <lunaix/mm/cake.h>
 #include <lunaix/mm/valloc.h>
 #include <lunaix/syslog.h>
 
+#include <lunaix/spike.h>
+
 #define BLOCK_EREAD 1
 #define BLOCK_ESIG 2
 #define BLOCK_ECRC 3
@@ -31,89 +35,108 @@ block_init()
 {
     lbd_pile = cake_new_pile("block_dev", sizeof(struct block_dev), 1, 0);
     dev_registry = vcalloc(sizeof(struct block_dev*), MAX_DEV);
+    free_slot = 0;
 }
 
 int
-block_mount_disk(struct hba_device* hd_dev)
+__block_read(struct device* dev,
+             void* buf,
+             unsigned int offset,
+             unsigned int len)
 {
-    int errno = 0;
-    struct block_dev* dev = cake_grab(lbd_pile);
-    strncpy(dev->name, hd_dev->model, PARTITION_NAME_SIZE);
-    dev->hd_dev = hd_dev;
-    dev->base_lba = 0;
-    dev->end_lba = hd_dev->max_lba;
-    if (!__block_register(dev)) {
-        errno = BLOCK_EFULL;
-        goto error;
+    int errno;
+    struct block_dev* bdev = (struct block_dev*)dev->underlay;
+    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, offset + rd_block, block, bsize)) {
+            errno = ENXIO;
+            goto error;
+        }
+        rd_size = MIN(len - acc_size, bsize);
+        memcpy(buf + acc_size, block, rd_size);
+        acc_size += rd_size;
+        rd_block++;
     }
 
-    if ((errno = __block_mount_partitions(hd_dev))) {
-        goto error;
-    }
+    vfree(block);
+    return rd_block;
 
 error:
-    kprintf(KERROR "Fail to mount hd: %s[%s] (%x)",
-            hd_dev->model,
-            hd_dev->serial_num,
-            -errno);
+    vfree(block);
+    return errno;
 }
 
 int
-__block_mount_partitions(struct hba_device* hd_dev)
+__block_write(struct device* dev,
+              void* buf,
+              unsigned int offset,
+              unsigned int len)
 {
-    int errno = 0;
-    void* buffer = valloc_dma(hd_dev->block_size);
-    if (!hd_dev->ops.read_buffer(hd_dev, 1, buffer, hd_dev->block_size)) {
-        errno = BLOCK_EREAD;
-        goto done;
+    int errno;
+    struct block_dev* bdev = (struct block_dev*)dev->underlay;
+    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, buf + acc_size, wr_size);
+        if (!bdev->hd_dev->ops.write_buffer(
+              bdev->hd_dev, offset + wr_block, block, bsize)) {
+            errno = ENXIO;
+            break;
+        }
+        acc_size += wr_size;
+        wr_block++;
     }
 
-    struct lpt_header* header = (struct lpt_header*)buffer;
-    if (header->signature != LPT_SIG) {
-        errno = BLOCK_ESIG;
-        goto done;
-    }
+    vfree(block);
+    return wr_block;
 
-    if (header->crc != crc32b(buffer, sizeof(*header))) {
-        errno = BLOCK_ECRC;
-        goto done;
-    }
+error:
+    vfree(block);
+    return errno;
+}
 
-    uint64_t lba = header->pt_start_lba;
-    int j = 0;
-    int count_per_sector = hd_dev->block_size / sizeof(struct lpt_entry);
-    while (lba < header->pt_end_lba) {
-        if (!hd_dev->ops.read_buffer(hd_dev, lba, buffer, hd_dev->block_size)) {
-            errno = BLOCK_EREAD;
-            goto done;
-        }
-        struct lpt_entry* entry = (struct lpt_entry*)buffer;
-        for (int i = 0; i < count_per_sector; i++, j++) {
-            struct block_dev* dev = cake_grab(lbd_pile);
-            strncpy(dev->name, entry->part_name, PARTITION_NAME_SIZE);
-            dev->hd_dev = hd_dev;
-            dev->base_lba = entry->base_lba;
-            dev->end_lba = entry->end_lba;
-            __block_register(dev);
-
-            if (j >= header->table_len) {
-                goto done;
-            }
-        }
+int
+block_mount_disk(struct hba_device* hd_dev)
+{
+    int errno = 0;
+    struct block_dev* bdev = cake_grab(lbd_pile);
+    strncpy(bdev->name, hd_dev->model, PARTITION_NAME_SIZE);
+    bdev->hd_dev = hd_dev;
+    bdev->base_lba = 0;
+    bdev->end_lba = hd_dev->max_lba;
+    if (!__block_register(bdev)) {
+        errno = BLOCK_EFULL;
+        goto error;
     }
 
-done:
-    vfree_dma(buffer);
-    return -errno;
+    return errno;
+
+error:
+    kprintf(KERROR "Fail to mount hd: %s[%s] (%x)\n",
+            hd_dev->model,
+            hd_dev->serial_num,
+            -errno);
 }
 
 int
-__block_register(struct block_dev* dev)
+__block_register(struct block_dev* bdev)
 {
     if (free_slot >= MAX_DEV) {
         return 0;
     }
 
-    dev_registry[free_slot++] = dev;
+    struct device* dev = device_add(NULL, bdev, "sd%c", 'a' + free_slot);
+    dev->write = __block_write;
+    dev->read = __block_read;
+
+    bdev->dev = dev;
+    dev_registry[free_slot++] = bdev;
     return 1;
 }
\ No newline at end of file