-
-
Notifications
You must be signed in to change notification settings - Fork 604
/
Copy pathvirtio-blk.hh
165 lines (136 loc) · 4.78 KB
/
virtio-blk.hh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
/*
* Copyright (C) 2013 Cloudius Systems, Ltd.
*
* This work is open source software, licensed under the terms of the
* BSD license as described in the LICENSE file in the top-level directory.
*/
#ifndef VIRTIO_BLK_DRIVER_H
#define VIRTIO_BLK_DRIVER_H
#include "drivers/virtio.hh"
#include "drivers/pci-device.hh"
#include <osv/bio.h>
namespace virtio {
class blk : public virtio_driver {
public:
// The feature bitmap for virtio blk
enum {
VIRTIO_BLK_F_BARRIER = 0, /* Does host support barriers? */
VIRTIO_BLK_F_SIZE_MAX = 1, /* Indicates maximum segment size */
VIRTIO_BLK_F_SEG_MAX = 2, /* Indicates maximum # of segments */
VIRTIO_BLK_F_GEOMETRY = 4, /* Legacy geometry available */
VIRTIO_BLK_F_RO = 5, /* Disk is read-only */
VIRTIO_BLK_F_BLK_SIZE = 6, /* Block size of disk is available*/
VIRTIO_BLK_F_SCSI = 7, /* Supports scsi command passthru */
VIRTIO_BLK_F_WCE = 9, /* Writeback mode enabled after reset */
VIRTIO_BLK_F_TOPOLOGY = 10, /* Topology information is available */
VIRTIO_BLK_F_CONFIG_WCE = 11, /* Writeback mode available in config */
};
enum {
VIRTIO_BLK_DEVICE_ID = 0x1001,
VIRTIO_BLK_ID_BYTES = 20, /* ID string length */
/*
* Command types
*
* Usage is a bit tricky as some bits are used as flags and some are not.
*
* Rules:
* VIRTIO_BLK_T_OUT may be combined with VIRTIO_BLK_T_SCSI_CMD or
* VIRTIO_BLK_T_BARRIER. VIRTIO_BLK_T_FLUSH is a command of its own
* and may not be combined with any of the other flags.
*/
};
enum blk_request_type {
VIRTIO_BLK_T_IN = 0,
VIRTIO_BLK_T_OUT = 1,
/* This bit says it's a scsi command, not an actual read or write. */
VIRTIO_BLK_T_SCSI_CMD = 2,
/* Cache flush command */
VIRTIO_BLK_T_FLUSH = 4,
/* Get device ID command */
VIRTIO_BLK_T_GET_ID = 8,
/* Barrier before this op. */
VIRTIO_BLK_T_BARRIER = 0x80000000,
};
enum blk_res_code {
/* And this is the final byte of the write scatter-gather list. */
VIRTIO_BLK_S_OK = 0,
VIRTIO_BLK_S_IOERR = 1,
VIRTIO_BLK_S_UNSUPP = 2,
};
struct blk_config {
/* The capacity (in 512-byte sectors). */
u64 capacity;
/* The maximum segment size (if VIRTIO_BLK_F_SIZE_MAX) */
u32 size_max;
/* The maximum number of segments (if VIRTIO_BLK_F_SEG_MAX) */
u32 seg_max;
/* geometry the device (if VIRTIO_BLK_F_GEOMETRY) */
struct blk_geometry {
u16 cylinders;
u8 heads;
u8 sectors;
} geometry;
/* block size of device (if VIRTIO_BLK_F_BLK_SIZE) */
u32 blk_size;
/* the next 4 entries are guarded by VIRTIO_BLK_F_TOPOLOGY */
/* exponent for physical block per logical block. */
u8 physical_block_exp;
/* alignment offset in logical blocks. */
u8 alignment_offset;
/* minimum I/O size without performance penalty in logical blocks. */
u16 min_io_size;
/* optimal sustained I/O size in logical blocks. */
u32 opt_io_size;
/* writeback mode (if VIRTIO_BLK_F_CONFIG_WCE) */
u8 wce;
} __attribute__((packed));
/* This is the first element of the read scatter-gather list. */
struct blk_outhdr {
/* VIRTIO_BLK_T* */
u32 type;
/* io priority. */
u32 ioprio;
/* Sector (ie. 512 byte offset) */
u64 sector;
};
struct virtio_scsi_inhdr {
u32 errors;
u32 data_len;
u32 sense_len;
u32 residual;
};
struct blk_res {
u8 status;
};
explicit blk(pci::device& dev);
virtual ~blk();
virtual std::string get_name() const { return _driver_name; }
void read_config();
virtual u32 get_driver_features();
int make_request(struct bio*);
void req_done();
int64_t size();
void set_readonly() {_ro = true;}
bool is_readonly() {return _ro;}
bool ack_irq();
static hw_driver* probe(hw_device* dev);
private:
struct blk_req {
blk_req(struct bio* b) :bio(b) {};
~blk_req() {};
blk_outhdr hdr;
blk_res res;
struct bio* bio;
};
std::string _driver_name;
blk_config _config;
//maintains the virtio instance number for multiple drives
static int _instance;
int _id;
bool _ro;
// This mutex protects parallel make_request invocations
mutex _lock;
std::unique_ptr<pci_interrupt> _irq;
};
}
#endif