Merge branch 'vfs-dev'
[lunaix-os.git] / lunaix-os / kernel / block.c
1 #include <hal/ahci/hba.h>
2 #include <klibc/stdio.h>
3 #include <klibc/string.h>
4 #include <lib/crc.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>
10
11 #include <lunaix/spike.h>
12
13 #define BLOCK_EREAD 1
14 #define BLOCK_ESIG 2
15 #define BLOCK_ECRC 3
16 #define BLOCK_EFULL 3
17
18 LOG_MODULE("BLOCK")
19
20 #define MAX_DEV 32
21
22 struct cake_pile* lbd_pile;
23 struct block_dev** dev_registry;
24
25 int free_slot = 0;
26
27 int
28 __block_mount_partitions(struct hba_device* hd_dev);
29
30 int
31 __block_register(struct block_dev* dev);
32
33 void
34 block_init()
35 {
36     lbd_pile = cake_new_pile("block_dev", sizeof(struct block_dev), 1, 0);
37     dev_registry = vcalloc(sizeof(struct block_dev*), MAX_DEV);
38     free_slot = 0;
39 }
40
41 int
42 __block_read(struct device* dev, void* buf, size_t offset, size_t len)
43 {
44     int errno;
45     struct block_dev* bdev = (struct block_dev*)dev->underlay;
46     size_t acc_size = 0, rd_size = 0, bsize = bdev->hd_dev->block_size,
47            rd_block = offset / bsize, r = offset % bsize;
48     void* block = vzalloc(bsize);
49
50     while (acc_size < len) {
51         if (!bdev->hd_dev->ops.read_buffer(
52               bdev->hd_dev, rd_block, block, bsize)) {
53             errno = ENXIO;
54             goto error;
55         }
56         rd_size = MIN(len - acc_size, bsize - r);
57         memcpy(buf + acc_size, block + r, rd_size);
58         acc_size += rd_size;
59         r = 0;
60         rd_block++;
61     }
62
63     vfree(block);
64     return rd_block;
65
66 error:
67     vfree(block);
68     return errno;
69 }
70
71 int
72 __block_write(struct device* dev, void* buf, size_t offset, size_t len)
73 {
74     int errno;
75     struct block_dev* bdev = (struct block_dev*)dev->underlay;
76     size_t acc_size = 0, wr_size = 0, bsize = bdev->hd_dev->block_size,
77            wr_block = offset / bsize, r = offset % bsize;
78     void* block = vzalloc(bsize);
79
80     while (acc_size < len) {
81         wr_size = MIN(len - acc_size, bsize - r);
82         memcpy(block + r, buf + acc_size, wr_size);
83         if (!bdev->hd_dev->ops.write_buffer(
84               bdev->hd_dev, wr_block, block, bsize)) {
85             errno = ENXIO;
86             break;
87         }
88         acc_size += wr_size;
89         r = 0;
90         wr_block++;
91     }
92
93     vfree(block);
94     return wr_block;
95
96 error:
97     vfree(block);
98     return errno;
99 }
100
101 int
102 block_mount_disk(struct hba_device* hd_dev)
103 {
104     int errno = 0;
105     struct block_dev* bdev = cake_grab(lbd_pile);
106     strncpy(bdev->name, hd_dev->model, PARTITION_NAME_SIZE);
107     bdev->hd_dev = hd_dev;
108     bdev->base_lba = 0;
109     bdev->end_lba = hd_dev->max_lba;
110     if (!__block_register(bdev)) {
111         errno = BLOCK_EFULL;
112         goto error;
113     }
114
115     return errno;
116
117 error:
118     kprintf(KERROR "Fail to mount hd: %s[%s] (%x)\n",
119             hd_dev->model,
120             hd_dev->serial_num,
121             -errno);
122 }
123
124 int
125 __block_register(struct block_dev* bdev)
126 {
127     if (free_slot >= MAX_DEV) {
128         return 0;
129     }
130
131     struct device* dev = device_addvol(NULL, bdev, "sd%c", 'a' + free_slot);
132     dev->write = __block_write;
133     dev->read = __block_read;
134
135     bdev->dev = dev;
136     dev_registry[free_slot++] = bdev;
137     return 1;
138 }