Merge branch 'device-sys'
[lunaix-os.git] / lunaix-os / kernel / block / 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     blk_mapping_init();
41 }
42
43 int
44 __block_read(struct device* dev, void* buf, size_t offset, size_t len)
45 {
46     int errno;
47     struct block_dev* bdev = (struct block_dev*)dev->underlay;
48     size_t acc_size = 0, rd_size = 0, bsize = bdev->hd_dev->block_size,
49            rd_block = offset / bsize, r = offset % bsize,
50            max_blk = (size_t)bdev->hd_dev->max_lba;
51     void* block = vzalloc(bsize);
52
53     while (acc_size < len && rd_block < max_blk) {
54         if (!bdev->hd_dev->ops.read_buffer(
55               bdev->hd_dev, rd_block, block, bsize)) {
56             errno = EIO;
57             goto error;
58         }
59         rd_size = MIN(len - acc_size, bsize - r);
60         memcpy(buf + acc_size, block + r, rd_size);
61         acc_size += rd_size;
62         r = 0;
63         rd_block++;
64     }
65
66     vfree(block);
67     return acc_size;
68
69 error:
70     vfree(block);
71     return errno;
72 }
73
74 int
75 __block_write(struct device* dev, void* buf, size_t offset, size_t len)
76 {
77     int errno;
78     struct block_dev* bdev = (struct block_dev*)dev->underlay;
79     size_t acc_size = 0, wr_size = 0, bsize = bdev->hd_dev->block_size,
80            wr_block = offset / bsize, r = offset % bsize;
81     void* block = vzalloc(bsize);
82
83     while (acc_size < len) {
84         wr_size = MIN(len - acc_size, bsize - r);
85         memcpy(block + r, buf + acc_size, wr_size);
86         if (!bdev->hd_dev->ops.write_buffer(
87               bdev->hd_dev, wr_block, block, bsize)) {
88             errno = EIO;
89             break;
90         }
91         acc_size += wr_size;
92         r = 0;
93         wr_block++;
94     }
95
96     vfree(block);
97     return wr_block;
98
99 error:
100     vfree(block);
101     return errno;
102 }
103
104 int
105 block_mount_disk(struct hba_device* hd_dev)
106 {
107     int errno = 0;
108     struct block_dev* bdev = cake_grab(lbd_pile);
109     strncpy(bdev->name, hd_dev->model, PARTITION_NAME_SIZE);
110     bdev->hd_dev = hd_dev;
111     bdev->base_lba = 0;
112     bdev->end_lba = hd_dev->max_lba;
113     if (!__block_register(bdev)) {
114         errno = BLOCK_EFULL;
115         goto error;
116     }
117
118     blk_set_blkmapping(bdev);
119     return errno;
120
121 error:
122     kprintf(KERROR "Fail to mount hd: %s[%s] (%x)\n",
123             hd_dev->model,
124             hd_dev->serial_num,
125             -errno);
126     return errno;
127 }
128
129 int
130 __block_register(struct block_dev* bdev)
131 {
132     if (free_slot >= MAX_DEV) {
133         return 0;
134     }
135
136     struct device* dev = device_addvol(NULL, bdev, "sd%c", 'a' + free_slot);
137     dev->write = __block_write;
138     dev->read = __block_read;
139
140     bdev->dev = dev;
141     strcpy(bdev->bdev_id, dev->name_val);
142     dev_registry[free_slot++] = bdev;
143     return 1;
144 }