X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/191737e1350a125739697af304730a0028ca01d5..bc4c6e1218d6903b07c32b11ea7d3c82c463686e:/lunaix-os/kernel/block.c diff --git a/lunaix-os/kernel/block.c b/lunaix-os/kernel/block.c index 0e28f66..b855910 100644 --- a/lunaix-os/kernel/block.c +++ b/lunaix-os/kernel/block.c @@ -1,11 +1,15 @@ #include +#include #include #include #include +#include #include #include #include +#include + #define BLOCK_EREAD 1 #define BLOCK_ESIG 2 #define BLOCK_ECRC 3 @@ -31,89 +35,104 @@ 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, size_t offset, size_t 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 = offset / bsize, r = offset % bsize; + void* block = vzalloc(bsize); + + while (acc_size < len) { + if (!bdev->hd_dev->ops.read_buffer( + bdev->hd_dev, rd_block, block, bsize)) { + errno = ENXIO; + goto error; + } + rd_size = MIN(len - acc_size, bsize - r); + memcpy(buf + acc_size, block + r, rd_size); + acc_size += rd_size; + r = 0; + 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, size_t offset, size_t 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 = offset / bsize, r = offset % bsize; + void* block = vzalloc(bsize); + + while (acc_size < len) { + wr_size = MIN(len - acc_size, bsize - r); + memcpy(block + r, buf + acc_size, wr_size); + if (!bdev->hd_dev->ops.write_buffer( + bdev->hd_dev, wr_block, block, bsize)) { + errno = ENXIO; + break; + } + acc_size += wr_size; + r = 0; + 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_addvol(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