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