1/*
2 * Copyright (c) 2014 ETH Zurich.
3 * All rights reserved.
4 *
5 * This file is distributed under the terms in the attached LICENSE file.
6 * If you do not find this file, copies can be found by writing to:
7 * ETH Zurich D-INFK, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group.
8 */
9
10#ifndef VIRTIO_DEVICES_VIRTIO_BLOCK_H
11#define VIRTIO_DEVICES_VIRTIO_BLOCK_H
12
13#include <dev/virtio/virtio_blk_dev.h>
14
15/*
16 * 5.2 Block Device
17 * The virtio block device is a simple virtual block device (ie. disk). Read
18 * and write requests (and other exotic requests) are placed in the queue, and
19 * serviced (probably out of order) by the device except where noted.
20 *
21 * Device ID = 2
22 *
23 * There is only a single virtio IO queue for this device
24 */
25
26/// the size of the VirtIO block device configuration spaces
27#define VIRTIO_BLOCK_CONFIG_SIZE 0x20
28
29/// the number of virtqueues for this device type
30#define VIRTIO_BLOCK_NUM_VIRTQUEUES 1
31
32#define VIRTIO_BLOCK_FLOUNDER_IFACE "vblk_host"
33
34/*
35 * --------------------------------------------------------------------------
36 * 5.2.3 Feature Bits
37 * --------------------------------------------------------------------------
38 */
39
40/// Request barriers are supported
41#define VIRTIO_BLOCK_F_BARRIER    0
42
43/// Maximum segment size is indicated in configuration structure
44#define VIRTIO_BLOCK_F_SIZE_MAX   1
45
46/// Maximum number of segments is indicated in configuration structure
47#define VIRTIO_BLOCK_F_SEG_MAX    2
48
49/// There is support for legacy geometry
50#define VIRTIO_BLOCK_F_GEOMETRY   4
51
52/// The disk is read only
53#define VIRTIO_BLOCK_F_RO         5
54
55/// The block size is indicated in configuration structure
56#define VIRTIO_BLOCK_F_BLK_SIZE   6
57
58/// SCSI command passthrough is supported
59#define VIRTIO_BLOCK_F_SCSI       7
60
61/// The cache flush command is supported
62#define VIRTIO_BLOCK_F_FLUSH      9
63
64/// the topology information is available
65#define VIRTIO_BLOCK_F_TOPOLOGY   10
66
67/// the length of the ID string
68#define VIRTIO_BLOCK_ID_BYTES      20
69
70/*
71 * ---------------------------------------------------------------------------
72 * Configuration Space
73 * ---------------------------------------------------------------------------
74 */
75
76/**
77 * \brief VirtIO block device topology information
78 */
79struct virtio_block_topology
80{
81    uint8_t num_logic_per_phys;  ///< number of logical blocks per physical
82    uint8_t alignment_offset;   ///< alignment offset
83    uint16_t min_io_size;       ///< suggested minimum IO size
84    uint32_t opt_io_size;       ///< suggested maximum IO size
85};
86
87/**
88 * \brief VirtIO block device geometry information
89 */
90struct virtio_block_geometry
91{
92    uint16_t cylinders;         ///< number of cylinders
93    uint8_t heads;              ///< number of heads
94    uint8_t sectors;            ///< number of sectors
95};
96
97/*
98 * --------------------------------------------------------------------------
99 * Device Configuration Layout
100 * --------------------------------------------------------------------------
101 */
102
103/**
104 * The device configuration layout as specified by 5.2.3.2
105 */
106struct virtio_block_config
107{
108    uint64_t capacity;          ///< the capacity in 512 byte sectors
109    uint32_t size_max;          ///< the maximum segment size
110    uint32_t seg_max;           ///< the maximum number of segments
111    struct virtio_block_geometry geometry;                 ///< device geometry
112    uint32_t blk_size;
113    struct virtio_block_topology topology;                 ///< topology information
114    uint8_t writeback;           ///< write back flag
115}__attribute__((packed));
116
117/*
118 * --------------------------------------------------------------------------
119 * Device Operations
120 * --------------------------------------------------------------------------
121 *
122 * The driver queues requests to the virtqueue, and they are used by the device
123 * (not necessarily in order).
124 */
125
126/*
127 * VirtIO Block Command types
128 */
129
130/// Virtio Block Device Request Type IN
131#define VIRTIO_BLOCK_T_IN     0x00000000
132
133/// Virtio Block Device Request Type OUT
134#define VIRTIO_BLOCK_T_OUT    0x00000001
135
136/// Virtio Block Device Request Type Flush
137#define VIRTIO_BLOCK_T_FLUSH  0x00000004
138
139/// Get device ID command
140#define VIRTIO_BLOCK_T_GET_ID 0x00000008
141
142/// Memory barrier
143#define VIRTIO_BLOCK_T_BARRIER 0x80000000
144
145/*
146 * VirtIO Status Field values
147 */
148
149/// Virtio Block Device Request Status OK
150#define VIRTIO_BLOCK_S_OK     0x0
151
152/// Virtio Block Device Request Status IO Error
153#define VIRTIO_BLOCK_S_IOERR  0x1
154
155/// Virtio Block Device Request Status Unsupported
156#define VIRTIO_BLOCK_S_UNSUPP 0x2
157
158/**
159 * 5.2.7.1 Legacy Interface: Device Operation
160 */
161struct virtio_scsi_reqhdr
162{
163    uint32_t errors;
164    uint32_t data_len;  ///< SHOULD be ignored by the driver.
165    uint32_t sense_len;  ///< number of bytes actually written to the sense buffer.
166    uint32_t residual;  ///< residual size, length - bytes actually transferred.
167};
168
169/**
170 * Block device request as defined in 5.2.5 Device Operation
171 */
172struct virtio_block_reqhdr
173{
174    uint32_t type;          ///< Type of the request. One of VIRTIO_BLOCK_T_*
175    uint32_t ioprio;        ///< Legacy devices only
176    uint64_t sector;        ///< Offset (multiplied by 512) where to read/write
177    /* the data and status follow */
178};
179
180/**
181 * stores additional information for the VirtIO block device
182 */
183struct virtio_device_blk
184{
185    struct virtio_device *vdev;
186    virtio_blk_t config_space;
187    void *config_addr;
188    struct virtqueue *vq;
189};
190
191/**
192 * \brief reads the device configuration and copies it into the local memory
193 *
194 * \param dev the block device to read the configuration space.
195 *
196 * \returns SYS_ERR_OK on success
197 */
198errval_t virtio_block_config_read(struct virtio_device_blk *dev);
199
200/**
201 * \brief   returns the block size of the device
202 *
203 * \param   dev the virtio block device
204 *
205 * \returns block size in bytes
206 */
207static inline uint32_t virtio_block_get_block_size(struct virtio_device_blk *dev)
208{
209    if (!virtio_device_has_feature(dev->vdev, VIRTIO_BLOCK_F_BLK_SIZE)) {
210        return 0;
211    }
212
213    return virtio_blk_block_size_size_rdf(&dev->config_space);
214}
215
216/**
217 * \brief   returns the capacity of the VirtIO block device in 512 segments
218 *
219 * \param   dev the virtio block device
220 *
221 * \returns capacity in 512-byte sectors
222 */
223static inline uint64_t virtio_block_get_capacity(struct virtio_device_blk *dev)
224{
225    return virtio_blk_capacity_sectors_rdf(&dev->config_space);
226}
227
228/**
229 * \brief   returns the maximum number of segments
230 *
231 * \param   dev the virtio block device
232 *
233 * \returns maximum number of segments if VIRTIO_BLOCK_F_SEG_MAX
234 *          0 otherwise
235 */
236static inline uint32_t virtio_block_get_segment_num(struct virtio_device_blk *dev)
237{
238    if (!virtio_device_has_feature(dev->vdev, VIRTIO_BLOCK_F_SEG_MAX)) {
239        return 0;
240    }
241    return virtio_blk_seg_num_max_rdf(&dev->config_space);
242}
243
244/**
245 * \brief   returns the maximum segment size
246 *
247 * \param   dev the virtio block device
248 *
249 * \returns maximum segment size if VIRTIO_BLOCK_F_SEG_MAX
250 *          0 otherwise
251 */
252static inline uint32_t virtio_block_get_segment_size(struct virtio_device_blk *dev)
253{
254    if (!virtio_device_has_feature(dev->vdev, VIRTIO_BLOCK_F_SIZE_MAX)) {
255        return 0;
256    }
257    return virtio_blk_seg_size_max_rdf(&dev->config_space);
258}
259
260/**
261 * \brief   returns the topology information
262 *
263 * \param   dev  the virtio block device
264 * \param   topo memory region to fill the topology information in
265 *               (only valid if VIRTIO_BLOCK_F_TOPOLOGY)
266 *
267 * \returns true if VIRTIO_BLOCK_F_TOPOLOGY
268 *          false otherwise
269 */
270bool virtio_block_get_topology(struct virtio_device_blk *dev,
271                               struct virtio_block_topology *topo);
272
273/**
274 * \brief   returns the blocksize of
275 *
276 * \param   dev the virtio block device
277 * \param   geo memory region to fill the geometry information in
278 *              (only valid if VIRTIO_BLOCK_F_GEOMETRY)
279 *
280 * \returns true if VIRTIO_BLOCK_F_GEOMETRY
281 *          false otherwise
282 */
283bool virtio_block_get_geometry(struct virtio_device_blk *dev,
284                               struct virtio_block_geometry *geo);
285
286/**
287 * \brief   handles the VirtIO block device common initialization.
288 *
289 * \param   dev     the VirtIO block device
290 * \param   setup   the setup information
291 *
292 * \returns SYS_ERR_OK on success
293 */
294errval_t virtio_block_init_device(struct virtio_device_blk *dev,
295                                  struct virtio_device_setup *setup);
296
297/**
298 * \brief   handles the VirtIO block device common initialization.
299 *
300 * \param   dev     the VirtIO block device
301 * \param   setup   the setup information
302 * \param   dev_cap the frame capability backing the device registers
303 *
304 * \returns SYS_ERR_OK on success
305 */
306errval_t virtio_block_init_device_with_cap(struct virtio_device_blk *dev,
307                                           struct virtio_device_setup *setup,
308                                           struct capref dev_cap);
309
310
311/*
312 * ----------------------------------------------------------------------------
313 * Additional functions for the host
314 * ----------------------------------------------------------------------------
315 */
316
317#ifdef __VIRTIO_HOST__
318/**
319 * stores additional information for the host side of the VirtIO
320 * block device
321 */
322struct virtio_host_blk
323{
324    struct virtio_device *host;           ///< the vhost of the block device
325    virtio_blk_t config_space;          ///< configuration space (mackerel)
326    void *config_addr;                  ///< raw pointer to the config space
327    void *config_tmp;                   ///< pointer to temporary config space
328    struct virtio_block_config config;  ///< configuration space values
329    struct virqueue_host *vq;           ///< the single virtqueue
330};
331
332/**
333 * \brief writes the configuration space values to the device configuration space
334 *
335 * \param bdev  the VirtIO host block device
336 *
337 * \return SYS_ERR_OK on success
338 */
339errval_t virtio_block_host_write_config(struct virtio_host_blk *bdev);
340
341#endif // __VIRTIO_HOST__
342
343#endif // VIRTIO_DEVICES_VIRTIO_BLOCK_H
344