1/* @title: Block Devices */
2#pragma once
3#include <block/bcache.h>
4#include <fs/detect.h>
5#include <sch/sched.h>
6#include <stdatomic.h>
7#include <stdbool.h>
8#include <stdint.h>
9#include <sync/spinlock.h>
10#include <thread/thread.h>
11
12struct block_device;
13struct bio_request;
14
15enum bdev_type {
16 BDEV_IDE_DRIVE,
17 BDEV_NVME_DRIVE,
18 BDEV_AHCI_DRIVE,
19 BDEV_ATAPI_DRIVE,
20};
21
22static inline const char *get_block_device_str(enum bdev_type type) {
23 switch (type) {
24 case BDEV_IDE_DRIVE: return "IDE DRIVE";
25 case BDEV_NVME_DRIVE: return "NVME DRIVE";
26 case BDEV_AHCI_DRIVE: return "AHCI CONTROLLER";
27 case BDEV_ATAPI_DRIVE: return "ATAPI DRIVE";
28 }
29 return "UNKNOWN DEVICE";
30}
31
32struct partition {
33 struct block_device *disk;
34 uint64_t start_lba;
35 uint64_t sector_count;
36 enum fs_type fs_type;
37 void *fs_data;
38 char name[16];
39 bool mounted;
40
41 struct vfs_node *(*mount)(struct partition *);
42};
43
44enum bdev_flags {
45 /* queue reordering is skipped */
46 BDEV_FLAG_NO_REORDER = 1,
47
48 /* coalescing is skipped */
49 BDEV_FLAG_NO_COALESCE = 1 << 1,
50
51 /* scheduling doesn't happen.
52 * this will just call sync
53 * requests, and immediately
54 * trigger the callback - used
55 * in things like RAMdisk. */
56 BDEV_FLAG_NO_SCHED = 1 << 2,
57};
58
59struct block_device {
60 enum bdev_flags flags;
61 enum bdev_type type;
62 enum fs_type fs_type;
63 void *fs_data;
64 char name[16];
65 uint64_t total_sectors;
66 bool is_removable;
67 void *driver_data;
68 uint32_t sector_size;
69
70 /* both of these take full priority over the async operations.
71 * do not pass go, do not collect two hundred dollars, submit instantly.
72 *
73 * these are sync and blocking
74 *
75 * these are not used in many areas though, and such, we can get away
76 * with instant submission for the most part*/
77 bool (*read_sector)(struct block_device *disk, uint64_t lba,
78 uint8_t *buffer, uint64_t sector_count);
79
80 bool (*write_sector)(struct block_device *disk, uint64_t lba,
81 const uint8_t *buffer, uint64_t sector_count);
82
83 /* immediate asynchronous submission */
84 bool (*submit_bio_async)(struct block_device *disk,
85 struct bio_request *bio);
86
87 struct bio_scheduler_ops *ops;
88 struct bio_scheduler *scheduler;
89 struct bcache *cache;
90 uint64_t partition_count;
91 struct partition *partitions;
92};
93
94static inline bool bdev_skip_coalesce(struct block_device *disk) {
95 return disk->flags & BDEV_FLAG_NO_COALESCE;
96}
97
98static inline bool bdev_skip_sched(struct block_device *disk) {
99 return disk->flags & BDEV_FLAG_NO_SCHED;
100}
101
102static inline bool bdev_skip_reorder(struct block_device *disk) {
103 return disk->flags & BDEV_FLAG_NO_REORDER;
104}
105